金融福尔摩斯修炼册-FULL GC篇

2023-11-10 08:40

本文主要是介绍金融福尔摩斯修炼册-FULL GC篇,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

点击「京东金融技术说」可快速关注

「引言」众里寻他千百度,蓦然回首,还是垃圾回收;内存占用过高,cpu负载居高不下,如何高效的借助工具来排查问题,让我们跟随本文来抽丝剥茧,让头疼的垃圾回收和full gc问题浮出水面...

  报    警

上周四微信上收到智能告警,某应用出现full gc频繁问题,初步观察了下sgm和线上机器情况,定位问题。每次告警都是对我们每个金融消防员的考验:如履薄冰,胆战心惊。

  立 案 调 查

  • 分析依据:发生fullGC的最常见情况是老年代或者永久代空间不足时。

  • 现场分析:通过SGM查看老年代和永久代的空间占比剩余空间还有一定比例,不至于发生fullGC,发生原因最后分析。

另外sgm上看了下jvm监控,发现堆内存从14号上午窜上去后再没下来过,下面这个图很容易定位是发生了内存泄漏,以下的思路就顺着定位内存泄漏的程序进行

  • 排查:看了下mapi代码提交记录,近期无上线,初步排除新上线代码问题。

在sure上使用jmap命令,发现char占据大量内存,怀疑存在大字符串。

周五找运维下了一份详细的dump文件,使用亮哥之前分享过的IBMHeapAnalyzer工具,分析发现问题可能出在EnterRealNameApplyUploadImgReqModel类里,这个类是用于实名申请时图片上传接口的入参实体类,里面包含了图片的base64的string串,占用较大空间。

排查mapi底层biz系统,查看EnterRealNameApplyUploadImgReqModel对应的实现类,发现biz中有对图片大小进行限制,最大为2M,但是mapi无限制,怀疑可能为此接口中上传图片过大。

经磊哥点拨,发现sdk中对base串做了加密,并在mapi中做了解密处理,加解密工具为静态(static)工具方法,可能导致内存泄漏。

定位到问题后,再使用亮哥推荐的visualVM插件,在本地启了mapi应用,在sdk写了个死循环去调图片上传接口,并故意将照片设置为3M,同时在idea的VM Option中JVM内存调至300M,此时效果如下:

可以很清楚的发现,old区增长速度特别快,同时gc次数频繁,并且无法有效的降低old区占用,old区整体呈现递增趋势,很容易发生内存溢出,经过之前的定位流程,猜测为图片本身较大,在亚当区无法容纳该对象时,直接塞到old区,同时加解密方法为静态方法,被持续引用,导致无法进行垃圾回收,导致old区持续递增。

 

  定    案

处理方案:

  • 生产服务器的内存为8G,将堆内存从2G扩到4G

  • 图片上传接口不在走通用加解密流程,在sdk、mapi单独为其封装了一套特殊的加解密流程,base64串不进行加密,直接做拼接处理,其余参数做加解密。处理后效果如下:

处理后可以很明显的发现无论是Old Gen区的递增速度还是gc次数相较于之前发生了很大的变化,趋于正常。

 

  案中案-CPU分析

以上过程其实问题已经得到解决,但发现频繁报fullgc的机器,cpu一直占用在10%以上,怀着打破砂锅问到底的态度对cup的问题也进行了下分析:

1、通过top命令查看占用cpu过高的进程

可以看到占用cpu的进程PID为7975

2、通过命令查找到占用cpu最高的线程

命令:top -H -p [进程id] top –H –p 7975 

3、将线程号转化为16进制(jstack线程堆栈中使用的16进制)

printf "%x\n" [线程id]


4、 查找线程号对应的线程

执行: jstack [进程id] |grep -A 10 [线程id的16进制]

由上图可以看到,一直在占用CPU的线程是CMS垃圾回收线程,由于堆内存占用过高程序又不释放,垃圾回收线程一直在尝试回收内存导致cpu过高。

 

  并案分析-垃圾回收原因

上面再分析触发垃圾回收的时候留了一个小尾巴,为什么老年代和永久代占用不高的时候频繁的发生了full gc呢。由于此应用使用的是jdk1.6,垃圾回收器使用的是CMS,它是基于“标记--清除”算法实现的,特点是在收集结束的时候会有大量的空间碎片产生。空间碎片太多的时候,将会给大对象的分配带来很大的麻烦,往往会出现老年代还有很大的空间剩余,但是无法找到足够大的连续空间来分配当前对象的,只能提前触发 full gc。如果jdk调整为1.7u4及以上即可使用G1垃圾回收算法不会产生大量的空间碎片。

 

  结 案 总 结

JVM问题一般不是很容易遇到,程序有bug或者并发量大的时候均可能导致jvm异常,通过以上问题的分析过程及以往的经验简单总结下排查jvm问题的一般思路:

  • 查看jvm内存和机器CPU情况

  • 内存占用过高,可能是发生内存泄漏,需要导出dump文件借助mat或者是IBM HeapAnalyze来分析内存中哪些对象占比比较高,那些实例较多的对象需要重点分析

  • cpu占用过高时可以通过步骤4的分析定位到具体的线程,程序编码中用到多线程的地方一定要给线程起个有意义的名字不要用默认的名字,这样出问题时方便定位。

上面只是个大概的流程,具体问题还需具体分析,重点还是需要掌握jvm原理并灵活应用


京东金融技术说&技术课堂

   ▼▼▼     

由京东金融-技术研发部策划组织

倡导“原创·实用·技术·专业”

致力于分享技术领域实战经验与技术干货

线上订阅“京东金融技术说”,线下聆听“技术课堂”

为加强技术分享、总结沉淀,提升金融技术影响力而搭建的线上线下融合交流平台

不只一技之长 · 我有N技在手

 咨询、建议、合作请联系:刘嘉璐(liujialu)/张明瑛(zhangmingying3)

这篇关于金融福尔摩斯修炼册-FULL GC篇的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/381574

相关文章

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

佰朔资本:沪指跌0.23%,金融板块集体上扬,半导体等板块下挫

6日早盘,沪指盘中轰动回落,深证成指、创业板指弱势下探,上证50指数逆市上扬,场内超4400股飘绿。 到午间收盘,沪指跌0.23%报2782点,深证成指跌1.01%,创业板指跌1.29%,上证50指数微涨0.05%,两市合计成交3502亿元。 盘面上看,半导体、家居、医药、酿酒、地产等板块走低,保险、券商、银行板块团体上扬,汽车拆解、海南自贸概念等生动。  5月下旬以来,大盘阶段性轰动整固,

一个金融网站的SEO优化技巧案例

前面写了两篇文章被大家评定为内容过于基础,建议添加一些实战案例。今天深圳SEO就把自己的一个金融站的实战案例分享给大家。 网站目的:1,外币兑换业务2,网站要有一定的流量3,提升权重以便以后开展其它业务 策略:因为外币兑换与汇率查询词语相关性较强,且流量比较大,因此决定以汇率查询相关词尾主词,顺带着将外币兑换业务一起进行推广。 第一步:关键词筛选 我主要是用两个工具战神和追词。 既然已经

Tushare库:Python金融数据分析的利器

文章目录 Tushare库:Python金融数据分析的利器一、引言二、Tushare库的安装与基础应用1、安装Tushare2、基础用法1.1 导入Tushare库1.2 获取数据 三、深入应用:案例分析1、股票收益策略模拟1.1 数据获取与处理1.2 策略模拟 四、总结 Tushare库:Python金融数据分析的利器 一、引言 在金融数据分析领域,Python因其强大

《程序员修炼之道》读书笔记(8):注重实效的项目

第8章:注重实效的项目 随着项目开动,我们需要从个体的哲学与编码问题,转向为项目级别的问题。 本章将讨论影响项目成败的几个关键区域。 41《注重实效的团队》 本书在先前讨论了帮助程序员个体更好的方法,这些方法对团队也有效。 下面将针对团队,来重述前面部分章节。 不要留破窗户。团队不应该容忍那些小小的、无人修正的不完美。煮青蛙。团队更容易被煮熟,因为每个人都觉得别人会在监视环境的变化。交流

Spark学习之路 (十四)SparkCore的调优之资源调优JVM的GC垃圾收集器

《2021年最新版大数据面试题全面开启更新》 欢迎关注github《大数据成神之路》 目录 一、概述 二、垃圾收集器(garbage collector (GC)) 是什么? 三、为什么需要GC? 四、为什么需要多种GC? 五、对象存活的判断 六、垃圾回收算法 6.1 标记 -清除算法 6.2 复制算法 6.3 标记-整理算法 6.4 分代收集算法 七、垃圾收集器 7.1 Serial收集器

Kafka 为了避免 Full GC,竟然还在发送端设计了内存池,自己管理内存,太巧妙了...

一、开篇引出一个 Full Gc 的问题 在上一篇文章中,我们讲到了 Kafka 发送消息的八个流程,并且着重讲了 Kafka 封装了一个内存结构,把每个分区的消息封装成批次,缓存到内存里。 如下图所示: 上图中,整体是一个 Map 结构,Map 的 key 是分区,Map 的值是一个队列;队列里有一个个的小批次,里面是很多消息。 这样好处就是可以一次性的把消息发送出去,不至于来一条发送一条,

JVM中的GC过程

堆内存结构:在详细讨论GC过程之前,需要了解JVM堆内存的结构。JVM堆内存通常被分为新生代(Young Generation)和老年代(Old Generation),其中新生代又进一步细分为Eden区(Eden Space)和两个Survivor区(S0和S1,也称为From和To区)。从JDK 1.8开始,永久代(Permanent Generation)被元空间(Metaspace)所取代

Spark GC 调优

我们的Spark环境目前主要问题是数据量大后一些task的GC Time 特别长,多则几分钟,少则几十秒,实在不能忍受。参考databricks的 Tuning Java Garbage Collection for Spark Applications对我们的环境优化后,效果比较明显。 选择垃圾收集器 如果分配给单个Executor的Heap足够大(我认为超过32G)时使用G1,

GC overhead limit exceeded : Spark

我在运行Spark程序的时候报错 java.lang.OutOfMemoryError:GC overhead limit exceeded 伴随着通常有: java.lang.OutOfMemoryError:Java heap spaceorg.apache.spark.shuffle.FetchFailedException:Failed to connect to ... 这是