真实线上OOM溢出借助MAT工具排查(原创)

结论

先说结论,后端服务消费到了kafka的超大消息,导致解析Json消息时OOM内存溢出了。

背景

有天,快下班时用户反馈说系统不可用了,加班排查了一晚上给解决了。

确定问题

1查CPU

登服务器,top命令监控当时CPU情况,发现有个java进程CPU飙升到100%了。
真实线上OOM溢出借助MAT工具排查(原创)_第1张图片

2定位系统

使用 ps -ef | grep java 命令,查这台服务器运行的所有java进程PID,发现cpu飘高的进程正好是我们XX系统出的问题,导致系统不可用。

3定位问题

再结合系统logback的error.log异常日志文件,发现OutOfMemoryError: Java heap spac,更证实了OOM堆内存溢出,导致的问题。
此外,还发现个问题:KafkaMessageListenerContainer异常了,难道系统用的Kafka接收消息出了问题?在这先埋下伏笔
真实线上OOM溢出借助MAT工具排查(原创)_第2张图片

分析问题

1下载dump文件

dump文件定义: dump文件是java虚拟机内存在某一时间点的快照文件,一般是.hprof的扩展名文件。
结合系统设置的生产环境JVM参数,可见:-Xmx1024m -Xms1024m -Xss512k
在这里插入图片描述
Xms:堆内存的初始大小,默认为物理内存的1/64
Xms:堆内存的最大大小,默认为物理内存的1/4
Xss:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
-XX:+HeapDumpOnOutOfMemoryError 表示当JVM发生OOM时,自动生成dump文件,dump文件在:KaTeX parse error: Expected group after '_' at position 23: …G_PATH}java_pid_̲{APPNAME}%t%p.hprof 路径下。
找到该dump文件路径,用sz命令下载该dump文件
真实线上OOM溢出借助MAT工具排查(原创)_第3张图片

2了解MAT工具

MAT(Memory Analyzer Tool)定义:一种内存分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。使用内存分析工具从众多的对象中进行分析,快速的计算出在内存中对象的占用大小,看看是谁阻止了垃圾收集器的回收工作,并可以通过报表直观的查看到可能造成这种结果的对象。
在eclipse上有mat的插件,或者苹果电脑有也有单独下载的mac版本mat,均可百度自行安装。

3导入mat分析:

按图下图所示,导入文件
真实线上OOM溢出借助MAT工具排查(原创)_第4张图片
导入完成,如下图所示
真实线上OOM溢出借助MAT工具排查(原创)_第5张图片
点击深蓝色的饼图部分,我们解读到:一共935.5MB的内存空间,KafkaMessageListenerContainer这个线程线程竟然占据了822.2M,其中Shallow size占了120B,Retained Size占了822.2M。
Shallow Size:对象自身占用的内存大小,不包括它引用的对象。
Retained Size:可理解为当前对象被GC后,从Heap上总共能释放掉的内存。
我们知道,频繁的内存泄露会导致内存溢出,大部分因为没及时垃圾回收清除对象释放内存空间,接着点击Leak Suspects(内存泄露建议)按钮如下:
真实线上OOM溢出借助MAT工具排查(原创)_第6张图片
已经再次提示了:KafkaListenerEndpointContainer 这个线程,本地变量,占据了862,169,408 (87.89%) bytes
查看堆栈信息,点击see stackstrace,如下图,定位到了具体哪行的问题代码

结合代码得知,就是这第109行的代码,做json解析时出问题导致,
真实线上OOM溢出借助MAT工具排查(原创)_第7张图片我这代码大概逻辑是:kafka接收到json格式的消息后,再执行这行代码做json解析。
我们再返回上一步,点击Details看详情:
真实线上OOM溢出借助MAT工具排查(原创)_第8张图片
进入发现了,熟悉的消息格式,右键把该消息复制为文件后,发现这个消息居然占:169MB!
该消息平常就几十到几百KB。
真实线上OOM溢出借助MAT工具排查(原创)_第9张图片

在这里插入图片描述

4 结论分析

至此,我们得出结论:某天线上突然有个超大(169MB)的消息要消费,解析json时导致的。

改进措施

把上述有问题的代码,前面加上过滤,只处理指定阈值大小内(消息的字符串长度在2097152以内)的消息,才做json解析,否则业务上视为异常消息,不处理。

你可能感兴趣的:(线上问题排查,java,开发语言,kafka,linux)