【JVM调优】频道服务 FullGC频率优化

一.背景

核心服务高峰期FGC频率过高,优化FGC频率,提高核心服务稳定性,本次以频道服务 nn-channel-business 为案例

Java环境:JDK8

 

二.优化前数据

1.JVM 启动参数如下

-Dname=nn-channel-business  -Dfile.encoding=utf-8 -Dspring.profiles.active=prod -Duser.timezone=Asia/Shanghai -Xms3072M -Xmx3072M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/logs/ -Dlog4j2.formatMsgNoLookups=true  -Dlog4j.formatMsgNoLookups=true  -javaagent:/skywalking-agent/agent/skywalking-agent.jar -Dskywalking.agent.service_name=nn-channel-business -Dskywalking.collector.backend_service=xx.xx.xx.xx:11800

垃圾回收器组合

  PS Scavenge(年轻代) + PS MarkSweep(也叫做 Parallel Old)(老年代)

内存分配

  年轻代:1G,其中,因为以上垃圾收集器组合,年轻代内存空间(Eden区 和 S区)会自适应动态分配内存,实际Eden区空间:970~990M,Surviror区空间 10~30M

  老年代:2G

2.JVM监控数据

日期:2025/04/04-2025/04/07

QPS:单实例峰值20QPS

image

image

三.原因分析

可能的原因如下:

1. 业务代码 & 第三方框架内存泄漏

2. 大对象频繁创建,直接分配老年代

3 .内存分配不合理,内存设置过小

4. 系统负载过高,高并发请求,大数据量的业务操作

 

四.问题排查过程

1. 业务代码 & 第三方框架内存泄漏

分析:查询高峰期内存快照,查询最大的内存占用是char[]对象

image

分析引用,关注320M的char数组对象,可以看到FastJSON序列化导致大量的引用

image

查询到GitHub有类似 issue

地址:https://github.com/alibaba/fastjson/issues/3751

问题描述:单个线程对应的ThreadLoacl存在128K 本地缓存,目的缓存序列化的字符串,提高序列化效率,但也导致了内存浪费

频道服务 tomcat 主线程数量 和 openfeign + hystrix 线程池 数据量合计在500,预计最高占用不超过100M内存,业务侧可接受

结论

由于JSON序列化导致的内存占用对FGC的影响较小,由于这块内存是缓慢增加至128K后会稳定不会上升,对于老年代的FGC的影响在4%(100M/2048M)

因此JSON序列化内存占用这个原因不是导致FGC频繁的原因,且内存快照没有发现其他的内存泄漏场景,因此该可能性可以排除

 

2. 大对象频繁创建,直接分配老年代

分析

分析目前频道业务场景,核心业务接口

/channel/business/findServerAndPluginByServerId/{serverId} 内嵌调用,查询语音房列表和组队列表(全量返回)    

/channel/business/enterPersonalTopicServerById 客户端调用,查询语音房列表和组队列表(全量返回)

1.高峰期以上两个接口调用趋势与DAU增长趋势一致

2.以上两个接口会返回大数组对象(最高1500个语音房),数组对象分配需要连续的内存空间,考虑是否因为年轻代内存空间不足导致

基于以上考虑,需要进一步确认是Eden区内存不足还是Surviror区内存不足

处理方案

1.Eden区内存空间不足

调整JVM参数,增加启动参数: -Xmn1536M

数据如下:改善不明显

image

2. Survivor内存空间不足

调整JVM参数,考虑到垃圾收集器动态分配内存的问题,增加启动参数:-XX:-UseAdaptiveSizePolicy -XX:SurvivorRatio=8

数据如下:改善明显,降低至1.5FGC次/天

image

结论

综上,可以确认是因为Survivor区内存空间不足对应FGC的频率较大,由于内存分配的需要连续的空间,年轻代Eden区发生GC时,Survivor空间无法支撑对象分配,因此直接分配到老年代

 

3 .内存分配内存设置过小,垃圾收集器选用不合理(TODO )

1. 综合问题2的结论,在现有内存分配和垃圾收集器组合的情况下(3G),优化效果已达预期

2. 垃圾收集器选用不合理 //TODO 后续可以分析对比CMS 和 PS 的效率

 

4. 系统负载过高,高并发请求,大数据量的业务操作

1.无相关业务操作

 

五.总结

问题原因

频道业务形态,具有连续的大的数据对象,Eden区GC后,Survivor空间分配过小,对象直接分配到老年代,导致老年代FGC频率过高原因

解决方案

JVM 参数增加参数,禁止动态分配,固定Eden区和S区大小

-XX:-UseAdaptiveSizePolicy -XX:SurvivorRatio=8

优化效果

高峰期FGC频率由 8次-->1.5次,降低 80% 

 

TODO

  1. 优化效果 是 在基于NN客户端(Web和PC)  现有业务场景和DAU 下的优化结果,如发生业务场景变更或DAU波动,需要进一步关注数据指标;
  2. 调研 CMS & PS 垃圾回收器在频道业务场景下的垃圾回收效率,关注对比数据,确认是否有进一步优化的空间;

 

posted @ 2025-08-26 23:34  听风是雨  阅读(16)  评论(0)    收藏  举报
/* 看板娘 */