图12 异步改同步后总线程数减少
5.优化 GC
优化 GC,减少 GC 的停顿时间,提高接口的性能。
1 )分析
首先看超时时间点是否有 Full GC,没有再看下 Yong GC 是否有明显的毛刺,如下图可以看到 3 个明显的毛刺。
图13 Yong GC时间
如果超时的时间点(如下图)可以对应上 GC 毛刺时间点,那可以确认问题是由于Yong GC 导致。
图14 客户端调用服务端超时次数
2)解决方案
- 通用性 JVM 参数调优
检查 -Xmx -Xms 这两个值设置的是否一样,如果不一样 JVM 在运行时会根据实际情况来动态调整堆大小,这个调整频繁会有性能开销,并且初始化堆较小的话,GC 次数会比较频繁。
效果:-Xmx3296m -Xms1977m 改成 -Xmx3296m -Xms3296m 后效果如下图所示,频率和时间都有明显的下降。
图15 通用性JVM参数调优后效果
背景:如果没有设置新生代最大值和最小值或者只设置了最大值和最小值中的一个,那么 G1 将根据参数 G1MaxNewSizePercent(默认值为60)和 G1NewSizePercent(默认值为5)占整个堆空间的比例来计算最大值和最小值,会动态平衡来分配新生代空间。
JVM刚启动默认分配新生代空间是总堆的 5%,随着流量的增加,新生代很容易就满了,从而发生 Yong GC,下一次重新分配更多新生代空间,直到从默认的 5% 动态扩容和合适的初始值。这种配置在发布接入流量或者大流量涌入时容易发生频繁的 Yong GC。
针对这类问题,优化方案是调大 G1NewSizePercent,调大初始值,让 GC 更加平稳。这个值需要根据业务场景参考GC日志中Eden初始大小分布来设置,太大可能会导致 Full GC 问题。
以查询引擎为例,根据 GC 日志分析,新生代大小占堆比例在 35% 后相对平稳,设置的参数为:
-XX: UnlockExperimentalVMOptions -XX:G1NewSizePercent=35
效果:优化后效果如下图,可以看到优化之后 GC 次数从 27次/min 降低到 11次/min,GC 时间从 560ms 降低到 250ms。