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

本文详细记录了一次由于消费Kafka超大消息(169MB)导致的Java后端服务OOM问题的排查过程。通过CPU监控、日志分析及MAT工具,定位到Json解析时的内存溢出,分析了JVM参数配置,并提出了解决方案:限制消息大小并过滤超出阈值的消息。
摘要由CSDN通过智能技术生成

结论

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

背景

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

确定问题

1查CPU

登服务器,top命令监控当时CPU情况,发现有个java进程CPU飙升到100%了。
在这里插入图片描述

2定位系统

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

3定位问题

再结合系统logback的error.log异常日志文件,发现OutOfMemoryError: Java heap spac,更证实了OOM堆内存溢出,导致的问题。
此外,还发现个问题:KafkaMessageListenerContainer异常了,难道系统用的Kafka接收消息出了问题?在这先埋下伏笔
在这里插入图片描述

分析问题

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文件
在这里插入图片描述

2了解MAT工具

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

3导入mat分析:

按图下图所示,导入文件
在这里插入图片描述
导入完成,如下图所示
在这里插入图片描述
点击深蓝色的饼图部分,我们解读到:一共935.5MB的内存空间,KafkaMessageListenerContainer这个线程线程竟然占据了822.2M,其中Shallow size占了120B,Retained Size占了822.2M。
Shallow Size:对象自身占用的内存大小,不包括它引用的对象。
Retained Size:可理解为当前对象被GC后,从Heap上总共能释放掉的内存。
我们知道,频繁的内存泄露会导致内存溢出,大部分因为没及时垃圾回收清除对象释放内存空间,接着点击Leak Suspects(内存泄露建议)按钮如下:
在这里插入图片描述
已经再次提示了:KafkaListenerEndpointContainer 这个线程,本地变量,占据了862,169,408 (87.89%) bytes
查看堆栈信息,点击see stackstrace,如下图,定位到了具体哪行的问题代码
在这里插入图片描述
结合代码得知,就是这第109行的代码,做json解析时出问题导致,
在这里插入图片描述我这代码大概逻辑是:kafka接收到json格式的消息后,再执行这行代码做json解析。
我们再返回上一步,点击Details看详情:
在这里插入图片描述
进入发现了,熟悉的消息格式,右键把该消息复制为文件后,发现这个消息居然占:169MB!
该消息平常就几十到几百KB。
在这里插入图片描述

在这里插入图片描述

4 结论分析

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

改进措施

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

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值