记录一次典型oom的处理过程

背景

有同学反馈收到应用RT的报警,其中的流量都来自于网关集群中的一台机器。因为负责网关,就上去看了下并进行排查。整体是一个比较明显的oom,这里只是记录下排查过程,老司机可以略过了。

初步现象

常规步骤,使用top 和jstat -gcutil 能直观的看到在拼命full gc。推测是出现了oom。
在这里插入图片描述

初步排查

一开始是用 jmap -histo:live [pid] >a.log 导出当前内存对象,为什么没有直接用jmap -dump:live 也是想偷懒,因为-dump 生成的文件太大,我们的服务器又跑在k8s上面,要拿回本地需要通过ftp 中转,想着能省就省。结果发现这个给后面埋了个大坑。
在这里插入图片描述
基于上面的结果,一度怀疑是sentinel 引起的问题。特别是对比了正常的机器上的内存分布
在这里插入图片描述
在上面浪费了大量时间,后面回过头看其实ConcurrentHashMap 占比这么高说明是缓存管理出现了问题。

进一步排查

老老实实用 jmap -dump:live,format=b,file=xxx.xxx [pid] 打印出详细的内存堆栈,拿到本地后用 IBM HeapAnalyzer(比较轻量) 或者MAT(大&慢,但是好用) 打开分析。
这里是先用了IBM HeapAnalyzer 进行分析。
在这里插入图片描述
从上面比较直观看到出现oom的类。这里只是看到单个的类比较大,从源码上看:在这里插入图片描述
会发现有块缓存没有设置长度和失效时间,这个很可能是导致oom的原因。

线上出现了新的问题

过了个周末,周一到公司之后同事反馈又出现了oom,还以为没解决上面的问题。于是又来了一遍,把内存dump 下来分析。
在这里插入图片描述
可以看到这次出现的类跟之前已经不一样了。这个时候发现 IBM HeapAnalyzer 的一个弱项,他不能直接显示字段名,只能显示类名,这个跟另一个同事使用的在线工具:https://heaphero.io/heap-index.jsp 有明显区别。但是在线工具打开dump 文件非常慢。这个时候就想着用MAT 打开看看。
下载MAT 打开官网:https://eclipse.dev/mat/downloads.php ,这个时候浏览器提示非安全的,又去找了下解决方法。
下载安装好之后,打开提示需要jdk1.17 ,我本地是1.11 。又去下了jdk1.17(https://www.oracle.com/java/technologies/downloads/#jdk17-mac),因为不想破坏本地jdk环境,所以需要配置MAT
在这里插入图片描述
增加2行,配置下载到本地的jdk路径

<string>-vm</string>
<string>/Users/ykdsg/opensource/jdk-17.0.8.jdk/Contents/Home/bin/java</string>

然后编辑 MemoryAnalyzer.ini 文件
在这里插入图片描述
新增配置
在这里插入图片描述
顺便改下jvm的内存,因为dump 文件通常比较大,太小的内存很容易报错。
调整完之后就可以顺利打开了。
在这里插入图片描述
可以比较直观的看到字段名。
在这里插入图片描述
可以推测是Map的value 类型是List,导致数据重复的增加。
在出现问题的机器上用arthas的getstatic 来看下内部情况:
先用arthas 连上jvm:

java -jar /alidata/deploy/arthas-boot.jar 45

再用getstatic 查看静态字段,-x 2 表示对象下钻的层级

getstatic com.yangt.hop.biz.util.DubboServiceCacheUtils serviceNameKeyMap -x 2

确实出现很多重复的数据,同一个key里面的值太多了,都打不下了:
在这里插入图片描述

最终解决

找到问题之后的解决方案就比较简单了,将List类型改为Set 就能解决这个问题。fix 之后再来看下这个字段的情况:
在这里插入图片描述
可以看到每个key 对应的数据基本就1条。

总结

如果要分析oom 还是老老实实用jmap -dump:live 以及配合MAT,大有大的用处。如果dump 的文件太大,本地内存吃紧的话可以考虑在服务器上建立索引,这个有看到过介绍但没试过。
arthas 是个好工具,对线上问题简直居家旅行必备。
对于缓存:如果是自己管理,并没有通过guava 之类的框架,还是要小心谨慎,并且尽量避免用list等非去重的结构。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值