首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >产线问题分析与解决系列:4告别周期性重启:G1垃圾收集器如何解决服务的内存堆积问题

产线问题分析与解决系列:4告别周期性重启:G1垃圾收集器如何解决服务的内存堆积问题

作者头像
李福春
发布2025-07-01 19:58:18
发布2025-07-01 19:58:18
13700
代码可运行
举报
运行总次数:0
代码可运行

内存周期性涨上去,一直告警。

程序员(小李):负责业务功能的开发和优化。 

运维(老张):负责系统的部署和监控。

 业务方(李总):负责业务需求和上线进度,强调快速扩张。


场景:会议室中,小李、老张和李总正在讨论OMS服务的内存问题及其解决方案。

李总(焦急地):小李,老张,这次OMS服务的内存问题很严重啊!每次版本迭代发布后,内存占用率72小时内就超过90%,触发告警。我们不得不周期性重启,但这样严重影响服务可用性和用户体验。我们的业务扩张速度这么快,这个问题必须马上解决!

小李(认真地):李总,我已经深入分析了这个问题。第一次排查时,我们通过Heap Dump和MAT工具检查了内存泄漏的可能性,但没有发现显式内存泄漏。第二次排查时,我们结合JVM监控数据和业务场景,发现老年代堆积是主要原因。默认的Parallel Old垃圾收集器无法及时回收中等生命周期对象,导致内存占用率快速上升。

老张(点头):对,我也监控到了这个问题。Full GC仅在老年代98%时触发,频率为24小时/次,且回收效率很低,每次只能释放5%-10%的空间。这种周期性重启的方式,不仅增加了运维成本,还无法从根本上解决问题。

小李:是的,我提出了一个解决方案:将垃圾收集器从Parallel Old切换到G1。G1的并发标记与混合回收机制可以针对性回收老年代的部分Region,避免全堆扫描。同时,G1的动态IHOP调整可以提前触发并发标记,防止老年代耗尽。

老张(赞许地):这个思路不错!G1的分区回收机制和可预测停顿模型确实比Parallel Old更适合我们的业务场景。我已经在测试环境中部署了G1,初步效果显示,发布后内存稳定在60%-75%,不再需要人工重启。

李总(稍微放松):听起来不错,但我们的业务扩张速度很快,数据量会越来越大。这些优化能支撑多久?

小李:李总,这些优化是经过充分测试的,能够支撑当前的数据量。未来如果数据量继续增长,我们可以考虑进一步优化,比如引入缓存机制或者分库分表。

老张:对,我这边也会加强监控,确保系统的稳定性。如果有性能瓶颈,我会第一时间通知小李。

李总(满意地):好,那你们抓紧时间上线这些优化。我们的业务不能停,内存问题必须尽快解决。

小李:明白,李总。我会尽快完成代码优化和测试,确保不影响业务。

老张:我这边也会配合小李,做好部署和监控工作。

李总(站起身):好,那就辛苦你们了!希望这次优化能彻底解决问题,让我们的业务继续快速扩张!



产生背景

OMS服务在每次版本迭代发布后,堆内存呈现阶梯式快速增长,72小时内内存占用率超过90%触发告警。为避免内存耗尽引发系统崩溃,运维团队采用周期性摘量重启临时缓解问题,导致以下影响:

  • 服务可用性波动:重启期间部分业务响应延迟,影响用户体验。
  • 运维成本激增:周期性人工摘量重启,人力投入与风险陡增。
  • 根因未解:缺乏系统性分析,问题长期存在。

分析过程

第一次排查:内存泄漏可能性分析
  1. 数据采集:
    1. 内存达70%、80%时分别触发Heap Dump,通过MAT工具解析。
    2. 检查Dominator Tree中Top对象(如缓存、线程池等),结合代码路径分析引用链。
  2. 结论:
    1. 未发现显式内存泄漏(如未释放的集合对象、资源句柄)。
    2. 可疑点:资源操作类(ResourceManager)存在大量短生命周期对象,但未直接关联堆内存增长。
第二次排查:JVM配置与业务场景关联分析
  1. 监控数据比对:
    1. GC日志:老年代占用率在发布后线性增长,Full GC仅在老年代98%时触发,频率为24小时/次,且回收效率低(回收后仅释放5%-10%空间)。
    2. JVM参数:默认使用Parallel Scavenge + Parallel Old组合,-Xmx4g,未配置自适应策略(如-XX:+UseAdaptiveSizePolicy)。
    3. 业务特征:发布后资源操作类接口调用量激增,产生大量中等生命周期对象。
  2. 根因推断:
    1. 老年代堆积:默认GC策略无法及时回收中等生命周期对象,导致对象过早晋升至老年代并堆积。
    2. Full GC低效:Parallel Old的单线程Full GC机制,在堆内存较大时停顿时间长,回收不彻底。

解决方案

  1. 策略调整目标:
    1. 提高老年代回收效率,避免对象长期堆积。
    2. 减少Full GC停顿时间,提升系统稳定性。

调整前:java8默认使用paral GC

代码语言:javascript
代码运行次数:0
运行
复制
-javaagent:/data/svr/tingyun-agent-java.jar 
-Xms4096m -Xmx4096m 
-XX:MetaspaceSize=256M 
-XX:MaxMetaspaceSize=512M 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/data/tmp/xxx/java_heapDump.hprof 
-XX:AutoBoxCacheMax=20000 
-Xloggc:/dev/shm/gc-dbu-mod-base.log 
-XX:+PrintGCDateStamps 
-XX:+PrintGCDetails 
-XX:+PrintGCApplicationStoppedTime -XX:+UseGCLogFileRotation
 -XX:NumberOfGCLogFiles=10 
 -XX:GCLogFileSize=1M
-Dapp.name=xxx-xxx
-Dapp.id=xxx-xxx

调整后:使用G1GC

代码语言:javascript
代码运行次数:0
运行
复制
-javaagent:/data/svr/tingyun-agent-java.jar 
-Xms4096m -Xmx4096m -XX:MetaspaceSize=256M 
-XX:MaxMetaspaceSize=512M -XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/data/tmp/xxx/eu_fr/java_heapDump.hprof 
-XX:AutoBoxCacheMax=20000 
-Xloggc:/dev/shm/gc-dbu-mod-oms.log 
-XX:+PrintGCDateStamps 
-XX:+PrintGCDetails 
-XX:+PrintGCApplicationStoppedTime 
-XX:+UseGCLogFileRotation 
-XX:NumberOfGCLogFiles=10 
-XX:GCLogFileSize=1M 
-XX:+UseG1GC
 -XX:MaxGCPauseMillis=200
-Dapp.name=xxx-oms-Dapp.id=xxx-oms-eu-fr

内存占用优化前后对比。

  1. 解决:
    • GC频率稳定,且由G1自动触发(非被动等待老年代满)。
    • 发布后内存稳定在60%-75%,无需人工重启。
    • G1的并发标记与混合回收机制,可针对性回收老年代部分Region,避免全堆扫描。
    • 动态调整IHOP,提前触发并发标记,防止老年代耗尽。
    1. 切换垃圾收集器为G1:
    2. 核心逻辑:
    3. 效果:

经验总结 

  • 多维度数据交叉验证:内存问题不能仅依赖单一工具(如MAT)分析堆转储,需结合JVM监控(GC日志、堆内存趋势)、系统级资源监控(如Linux内存占用)、业务流量波动等数据,避免陷入局部视角。
  • 重视GC策略与业务场景的适配性:CMS/Parallel等传统收集器在长生命周期对象多的场景下易导致老年代堆积,需根据业务特点(如高频资源操作、大对象分配)选择G1等现代收集器。
  • 参数调优需动态迭代:初始参数调整后需持续监控GC效率(如Mixed GC频率、晋升失败率),通过工具(如GCViewer)分析停顿时间分布,逐步优化阈值参数。

相关技术分享

G1垃圾收集器的核心优势

  • 分区回收机制:将堆划分为等大Region(默认2-32MB),优先回收垃圾比例高的区域,避免全堆扫描(传统CMS痛点)。
  • 可预测停顿模型:通过-XX:MaxGCPauseMillis(默认200ms)设定目标停顿时间,G1动态调整回收区域数量。
  • 并发标记能力:并发执行标记阶段(Concurrent Marking),减少STW时间,适合长生命周期对象多的场景。

根由分析:业务上有资源释放的比较慢,只有FullGC的时候才会释放一些,暂未彻底找到,只是提高了GC的频次来临时解决这个问题。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-05-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 李福春持续输出 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 产生背景
  • 分析过程
    • 第一次排查:内存泄漏可能性分析
    • 第二次排查:JVM配置与业务场景关联分析
  • 解决方案
  • 经验总结 
  • 相关技术分享
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档