现象
投放模块发生了一次告警,会员模块处理请求花了27ms,然而投放模块却认为超时(大于100ms),现象很诡异。
原因
产生这个原因,可能是dubbo线程池的问题、网络的问题和GC的问题。1.余量有70ms,线程池和网络都不会产生这么大的延时,大概率的GC的问题。进一步分析,发现在那个时间点,YGC时间达到了0.36s,一般YGC停顿大概都是十几毫秒,这个YGC却这么长,已经足够导致超时问题了,已经确认了原因。
然后,对比了投放模块的物理机和容器的GC时间,发现容器的GC时间总是比物理机的长。两者都不在一个数量级。
由此可以确认是容器GC的问题。
进一步研究搜索,原因是:
Java启动时候需要初始化ParNew线程数,当前的版本采用了宿主机的核心数,而没有采用容器分配的核心数。见jstack的图,ParNew的线程一共有28个,然而容器配置的为4U8G,两者相差具体。在停顿期间,GC线程会产生竞争,由此会导致GC时间急剧增加。
在jdk8u191中已经修复这个问题。
参考文献:
http://way.xiaojukeji.com/article/17231
解决
1.可以升级jdk。2.可以加上-XX:ParallelGCThreads=CPU_COUNT
参数。