51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

生产环境频繁堆内存使用率 90% 告警,调大内存竟然没有效果!记一次线上JVM 优化。

本文主要分享一次生产环境堆内存告警排查分析并解决的实操流程。内容全文 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 。 堆内存监控 老年代内存监控 Eden 内存监控

通过和运维沟通后了解到生产上 JVM 参数并没有做特殊配置。

线上环境使用 JDK 1.8 使用的是默认的垃圾收集器。新生代默认是:Parallel Scavenge 老年代默认是:Parallel Old

Parallel Scavenge 垃圾收集器核心关注吞吐量 gc时间/程序运行总时间 作为依据进行 GC。

这导致新生代和老年代基本是在接近填满时进行 GC, 即上述我们扩大内存后仍然会频繁报内存使用率过高的情况。

Parallel Scavenge 垃圾收集器没有固定的百分比阈值。如果需要减少Full GC的发生,通常需要调整老年代的大小或者调整整个堆的大小。

解决方案

根据上述问题分析可以有 2个解决方案:

  1. 调整老年代的大小或者调整整个堆的大小 这种方式还是会频繁出现内存告警

  2. 老年代更换为 CMS 垃圾收集器并配置固定百分比的阈值。

综合分析还是切换为 CMS 垃圾收集器,核心原因如下:

  1. CMS 可以配置 固定百分比的阈值

  2. Parallel Old 是并行垃圾收集器而 CMS 是并发垃圾收集器, CMS 性能要优于 Parallel Old

关于 CMS 参数配置推荐一个在线配置工具:

https://opts.console.heapdump.cn/

可以通过参数生成快速生成一个比较合理的参数配置 生成jvm 参数

生成的参数具体如下:

-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%左右告警,优化前后具体内存效果对比如下:

堆内存优化前后内存变化。 jvm 堆内存优化前后对比

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

优化后 CMS 垃圾收集器内存变化。 优化后老年代 - END -

赞(3)
未经允许不得转载:工具盒子 » 生产环境频繁堆内存使用率 90% 告警,调大内存竟然没有效果!记一次线上JVM 优化。