记一次线上内存溢出问题排查过程-高可用

起因

我负责的APP项目系统,简称A系统。在与其它项目T系统不在同一个服务器的情况下,发现T系统重启会导致A系统并发量瞬间暴增,最后导致A系统内存溢出挂掉。

排查

1、服务器日志排查

通过XShell6工具查看系统服务日志,下载日志并排查在服务器宕机的时间内的异常,
在这里插入图片描述
异常信息中没有具体哪个接口、方法导致,于是找运维要了heapdump文件,利用JDK带的jvisualvm工具进行分析

2、通过工具分析

工具位置,在JDK中的bin目录下,工具的具体使用请自行查阅
在这里插入图片描述
将heapdump文件导入分析:
在这里插入图片描述
通过工具定位的两个接口。

3、接口压测

将定位到的接口交给测试进行压测,压测的结果的是其中一个接口在并发量50就出问题,进行优化再上线。

4、等待T系统发布版本

发布版本后发现A系统还是挂掉

5、统计A系统宕机区间的接口访问量

统计命令
sed -n ‘/2021-12-22 21:27:01/,/2021-12-22 21:29:47/p’ catalina.out|grep 第三方获取工单详情|wc -l
在这里插入图片描述
发现访问量在那个时候还是暴增,于是询问T系统使用接口的业务情况以及排查,发现他们的中间件使用异常,无法进行正常的ack机制,于是在重启的瞬间将积累的访问都重新调用了一遍。

6 最后

1、优化了接口,压测结果:1000并发量没有出现异常
2、T系统修改了BUG
3、运维修改了配置

#net.ipv4.tcp_tw_recycle = 1    将这个注释了

net.ipv4.tcp_keepalive_time = 500
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5

后面T系统重启两次,APP项目无异常,准备后续T系统再发版本重启系统,监测下情况。待续


后续系统还是偶尔会内存溢出,Java VisualVM只提供了一些基本的功能,无法具体定位问题。
要使用Eclipse Memory Analyzer来分析。

排查的结果是第三方重启时还是会多次调用一个接口,偶尔会不传参进行调用,导致接口查询了全表数据,数据量太大导致内存溢出

Eclipse Memory Analyzer下载地址:
https://www.eclipse.org/mat/downloads.php

扫描二维码关注公众号,回复: 15459501 查看本文章

排查过程

拿到dump文件

在这里插入图片描述

修改mat内存

因为dump文件超过1G,而mat初始大小为1024,不修改会打不开文件
在这里插入图片描述

在这里插入图片描述

打开文件

在这里插入图片描述
在这里插入图片描述
总共使用的内存为1.2G
Thread对象占用了755.2M
点击Leak Suspects查看具体的内存泄露报告
在这里插入图片描述
DETAILS
在这里插入图片描述
点击圈起来的,查看引用关系,下图,可以很清晰的看到是由于ArrayList中放了18W个byte数组造成的
在这里插入图片描述
回到details,点击选择Java basics-》Thread Details
通过线程中可能引起内存溢出时代码的执行位置,一一排查,最后定位
在这里插入图片描述
最后发现因为第三方参数未传必传参数id,而该方法也没有进行必填参数校验,导致该方法查询出全表数据(全表数据有18W多),这也是ArrayList中有18W个byte数组的原因。最终导致了内存溢出。

再次确认

通过本地配置和线上一样的内存-Xms1536m -Xmx1536m
在这里插入图片描述

再进行本地调用该方法并且不传参数,在第二次调用发生了线上一样的内存溢出报错
在这里插入图片描述

解决

对该方法进行必填参数校验,上线后没有再次发生内存溢出的问题

参考
Eclipse Memory Analyzer入门学习笔记
面试官:内存泄漏,内存溢出如何排查?

猜你喜欢

转载自blog.csdn.net/RoyRaoHR/article/details/122197013