年轻代GC回收时间不稳定,会出现突刺
下图是每分钟yong gc 所消耗的时间,没有规律的突刺。
年轻代gc 使用的是 ParNew 并发收集,

下图是每分钟yong gc 的次数,可以看出每分钟gc的频率比较稳定。

每分钟gc次数没有变化,gc时间增加了,说明某次gc时间变长了。
一般程序有问题,造成的结果是每次gc时间都比较久。
再看看系统cpu有没有问题,有可能cpu压力比较大

cpu的均值无变化,下面看下cpu峰值

可以看到cpu峰值不太稳定
这个时候结合前面年轻代GC不稳定,去机器上用jstack看下gc线程数。
1 | $ grep Gang jstack.log | awk '{print $3,$4,$5}' |uniq -c |
容器的资源是4核的,并行gc的线程数竟然有33个(这里宿主机48核,刚好对应上)
cpu 核数小于8 gc 线程数等于cpu核数,大于8的时候=8+(cpu数-8)*5/8
Parallel CMS Thread 并发的GC线程数(ParallelGCThreads+3)/4
猜测可能线程数太多,线程上下文切换影响了CPU 性能
接下来通过 jstack 查看线程id,nid线程id,0x412对应10进制1042

通过pidstat 查看进程下线程的上下文切换情况,自愿和非自愿切换都是非0

定位到问题&解决方案
在Docker中通过CGroup来限制内存和CPU,作为一种较新的技术,历史Java版本并不能自然的理解相应的资源限制。这个时候有2种解决方案:
方案一:
明确配置JIT和GC线程数
-XX:ParallelGCThreads
-XX:CICompilerCount
方案二:
JDK 8u191 后的版本可以识别容器的CPU限制,升级容器的JDK版本
升级后的cpu峰值效果对比,可以看到比较稳定。

年轻代GC时间也比较稳定
