jvm问题实录2-来自凌晨的线上堆内存使用率告警
线上现象(来自凌晨的问候)
- 凌晨3点线上项目在监控平台上开始报警(jvm堆内存占用报警超过80%,持续报警)
- 观察具体的监控图标(线程数平稳) 时间:2019-06-13 首先要看方法调用量有没有大量提升,通过排查没有
逻辑分析(定位问题大致方向)
- 通过当天监控数据分析,堆内存持续上升,在凌晨3点左右触及报警配置水位1800/2048 >80%,导致报警
- 非堆、cpu、线程数稳定
- 系统Young GC频繁,Full GC暂时没有
当前推论 :系统YGC已经不能回收太多堆内存,而FGC还没有执行,可能是因为老年代在持续增长,
需要查看当前机器自启动以来的历史数据参考(因为当前线上一次查询范围最大1天),
2019-06-10 ->11号 数据,和12号的比对,可以看出堆内存水位在缓慢上升,最终再13号凌晨出发报警。
接着推论 :
- 老年代持续上升,按照CMS的默认92%处理机制,如果是正常内存使用,我们不用管报警,达到高水位自动FGC,堆内存恢复低位,
- 但是如果是因为内存泄露引起的问题,那么按照目前速率可能会在2-3天后(也可能是618促销期间)出现内存溢出宕机。
线上验证
验证之前要小心,最好先把机器从集群摘除,因为FullGC会影响机器性能
接下来我们要验证一下是正常的使用还是内存泄露,采用手动触发一次FGC,执行histo命令
结论: 从监控可以看出,触发了FGC后,堆内存直接降到低水位,因此我们可以理解为是正常的内存增长,
后续的工作 : 1. 从dump及代码层面分析为什么老年代持续增长, 2. 更改一下监控报警配置 等优化
我们也可以通过监控看到刚才执行的FGC对方法性能的影响,
后记
讲个细节(为什么凌晨会持续报警)?
- 报警规则
- 长期运行后正好赶上了凌晨…
- 凌晨调用量小,YGC间隔大,内存在间隔期长时间高水位
troube shooting 三要素: 锻炼自己的逻辑思维、锻炼自己的技术能力、多看多查