服务频繁发生YoungGC的处理过程(合理压测)

By | 2021年6月22日

问题描述

最近一直在做项目的GC优化,因为服务在运行过程中频繁发生GC问题,虽然不是FullGC,但Young频繁GC也会影响线上服务的性能,优化的方向有两个,1.修改JVM参数 ,2.优化代码逻辑。查看当前线上JVM配置调整年轻代的大小可以缓解因内存分配太小而发生频繁GC的问题。本次优化的重点在于代码逻辑的实现,主要原因是:

  1. 在目前架构内,系统并不能通过改变eden区大小得到有效解决,年轻代内存区域调大,GC频率改善,但时长会变长。反之,作用也是相反。

  2. 频繁的GC和pause清理耗时又引起jvm内tomact线程数的增加,可通过监控观测到服务实例的tp99和tp95的能力逐渐降低

  3. 通过增加服务实例提升性能的效果不够明显,反而因为服务中定时任务更加频繁请求接口,造成下游服务的压力负担。

优化阶段

第一次优化,主要是去除代码中定时任务线程拉取下游接口数据的功能,因为每次会向年轻代申请大量的内存,关闭定时数据对比功能,数据对比逻辑中会对全量数据进行遍历,也会占用一部分年轻代的内存。

第二张图为监控三小时内优化后服务运行的YoungGC情况,GC次数已经明显降低,曲线波动幅度变小,GC频率在8分钟-10分钟。

image-20210617103828569

image-20210617103841016

第二次优化,重写数据对比功能,通过随机数据抽样生成小样本来进行对比,第二张图为运行一段时间后的GC情况,曲线中的锯齿状波动说明在定时数据对比时进行了内存申请。

image-20210617164901431

image-20210617164511338

压力阶段

优化阶段结束后对服务进行了压力测试,以分析在大量并发访问情况下GC的情况,这次测试也让我知道压力测试不是压力越大越好,要实际考虑服务器性能,合理的设置线程并发数和吞吐量来进行压测,不然效果可能会适得其反,无法得出有价值的结论,影响正常优化逻辑的判断。

图一图二分别时超量压测时旧版服务和新版服务的GC情况,无法看出哪个效果更好更明显,因为超过服务最大负载量。

image-20210618141854322

image-20210618141918411

在调整吞吐量后进行压力测试,在合理的吞吐范围内,通过图二可以看出GC情况降低很多,远没有旧版服务的GC频繁,明显可以看出优化后的效果。

image-20210618141519832

image-20210618141536471

我的总结

结论:性能优化的路很长,要了解的方向也很多,软件和硬件方面都要考虑,任何指标的变动都可能对整体服务性能造成影响,还是第一次对于年轻代GC进行优化,可能采用的方案并不正确,分析得到的结果也有错误,但也算是一种思路,仅供参考,最后还了解到压测的合理性,以前总觉得压测越大越好,只要压不崩就往崩了压,但其实这只是极端的压力测试,可以参考的意义并不大,尽量结合具体场景来进行测试,才能更准确的反映服务性能,得到预期的结果。

发表评论

电子邮件地址不会被公开。 必填项已用*标注