出品 | 程序员小奎· 转载请联系授权
本文主要分享一次生产环境堆内存告警排查分析并解决的实操流程。内容全文 2210字,预计花 5 分钟读完。问题背景
最近告警监控群频繁报服务内存使用率大于 90% ,具体告警内容如下:
告警级别: JvmCritical 告警类型: 堆内存使用率告警 告警详情: 服务 npp , 实例 1xx.1x.1x.3x 堆> 内存使用率大于90% ,当前使用率:95.29% 告警节点: 100.1x.1x.3x 故障应用: npp
看到这个问题第一时间联系运维堆现有服务调大内存的参数,由 1G 扩大为 1.5 G 。
扩大以后使用率告警没有之前那么频繁了,但是每天还会出现内存使用率 90%左右的告警。
问题分析
查看近 7 天的堆内存、新生代 Eden 区、老年代的内存使用情况,虽然内存调大了,但是基本都是快使用完才进行GC 。



通过和运维沟通后了解到生产上 JVM 参数并没有做特殊配置。
线上环境使用 JDK 1.8 使用的是默认的垃圾收集器。新生代默认是:Parallel Scavenge 老年代默认是:Parallel Old
Parallel Scavenge 垃圾收集器核心关注吞吐量 gc时间/程序运行总时间 作为依据进行 GC。
这导致新生代和老年代基本是在接近填满时进行 GC, 即上述我们扩大内存后仍然会频繁报内存使用率过高的情况。
Parallel Scavenge 垃圾收集器没有固定的百分比阈值。如果需要减少Full GC的发生,通常需要调整老年代的大小或者调整整个堆的大小。
解决方案
根据上述问题分析可以有 2个解决方案:
-
调整老年代的大小或者调整整个堆的大小 这种方式还是会频繁出现内存告警 -
老年代更换为 CMS 垃圾收集器并配置固定百分比的阈值。
综合分析还是切换为 CMS 垃圾收集器,核心原因如下:
-
CMS 可以配置 固定百分比的阈值 -
Parallel Old 是并行垃圾收集器而 CMS 是并发垃圾收集器, CMS 性能要优于 Parallel Old
关于 CMS 参数配置推荐一个在线配置工具:
https://opts.console.heapdump.cn/
可以通过参数生成快速生成一个比较合理的参数配置

生成的参数具体如下:
-Xmx2688M-Xms2688M-Xmn960M-XX:MaxMetaspaceSize=512M-XX:MetaspaceSize=512M-XX:+UseConcMarkSweepGC-XX:+UseCMSInitiatingOccupancyOnly-XX:CMSInitiatingOccupancyFraction=70-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses-XX:+CMSClassUnloadingEnabled-XX:+ParallelRefProcEnabled-XX:+CMSScavengeBeforeRemark-XX:ErrorFile=/log/hs_err_pid%p.log-XX:HeapDumpPath=/log-XX:+HeapDumpOnOutOfMemoryError
具体参数介绍如下:
-
-Xmx:最大堆内存 -
-Xms:最小堆内存 -
-Xmn:新生代的大小 -
-XX:MaxMetaspaceSize:最大元空间大小 -
-XX:MetaspaceSize:元空间大小 -
XX:+UseConcMarkSweepGC:使用 CMS 垃圾收集器 -
-XX:+UseCMSInitiatingOccupancyOnly :需要和 CMSInitiatingOccupancyFraction配置使用 -
-XX:CMSInitiatingOccupancyFraction:触发cms gc 的老生代使用率 需要和 UseCMSInitiatingOccupancyOnly 配配合使用 -
-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses :当调用 System.gc() 时,JVM 会启动 CMS(Concurrent Mark Sweep)垃圾收集器的并发收集,并尝试卸载不再需要的类。如果没有配置 JVM 将执行全堆的垃圾收集,而不是并发收集,也不会尝试卸载类。 -
-XX:+CMSClassUnloadingEnabled :CMS 的垃圾收集周期中,JVM 会尝试卸载不再需要的类 -
-XX:+ParallelRefProcEnabled :-XX:+ParallelRefProcEnabled,那么在垃圾收集过程中,JVM 会并行处理这些引用对象(SoftReference、WeakReference、FinalReference),从而提高垃圾收集的效率 -
-XX:+CMSScavengeBeforeRemark :CMS 的重新标记(Remark)阶段之前,JVM 会先执行一次新生代的垃圾收集。这样做的目的是减少重新标记阶段的工作量 -
XX:+HeapDumpOnOutOfMemoryError:当 JVM 遇到 OutOfMemoryError 时是否生成堆转储文件(heap dump)。
优化后的效果
优化后效果明显,一天内没有再出现内存使用 90%左右告警,优化前后具体内存效果对比如下:
堆内存优化前后内存变化。

优化前使用的是 Parallel Old 垃圾收集器 近 7天内存变化。

优化后 CMS 垃圾收集器内存变化。


本篇文章来源于微信公众号: 程序员小奎
微信扫描下方的二维码阅读本文

Comments NOTHING