while(true)引发的Dubbo应用假死

while(true)引发的Dubbo应用假死

现象:

当客户端向服务器发起调用的时候,Dubbo出现无法响应,客户端报超时异常,而且当客户端继续调用任何服务时,出现No provider available 异常。而此时服务器不见异常,偶尔报出OOM异常。

问题汇总

  • 客户端首次访问该接口超时
  • 客户端继续调用任何服务时,No provider异常或者超时
  • 服务端偶尔OOM异常
  • 服务端假死状态,难以attache到进程执行dump

客户端超时的问题,通过日志查看,是服务端到达超时时间无响应;客户端No provider问题,通过查看zookeepper是provider已经删除注册的节点信息。所以,都是服务端的错。

服务端问题排查

通过jvisualvm连接到服务端,客户端开始调用时,发现permgen平稳,和heap区在几秒内接近极限值,然后jvisualvm默默的挂了停止输出曲线图。服务端已经处于假死状态了。用jstack看了下线程,140个线程左右,大部分都是block状态。唯独服务的实现方法很忙 。

用bin下面的工具基本上没什么救。回到原始的办法。

查看服务代码一个while(true)在错误参数下无法跳出循环,一直创建对象。

打印GC详情,如下:
[Full GC [CMS: 81920K->81920K(81920K), 0.7013303 secs] 96703K->94980K(96704K), [CMS Perm : 43688K->43688K(65536K)], 0.7014547 secs] [Times: user=0.70 sys=0.00, real=0.70 secs]
[GC [1 CMS-initial-mark: 81920K(81920K)] 94980K(96704K), 0.0261988 secs] [Times: user=0.03 sys=0.00, real=0.03 secs]
[Full GC [CMS[CMS-concurrent-mark: 0.389/0.392 secs] [Times: user=0.44 sys=0.00, real=0.39 secs]
(concurrent mode failure): 81920K->81920K(81920K), 1.0097710 secs] 96703K->95669K(96704K), [CMS Perm : 43688K->43687K(65536K)], 1.0098518 secs] [Times: user=1.00 sys=0.02, real=1.01 secs]
[Full GC [CMS: 81920K->81920K(81920K), 0.6858801 secs] 96703K->96083K(96704K), [CMS Perm : 43687K->43687K(65536K)], 0.6859716 secs] [Times: user=0.66 sys=0.03, real=0.69 secs]
[GC [1 CMS-initial-mark: 81920K(81920K)] 96083K(96704K), 0.0240469 secs] [Times: user=0.03 sys=0.00, real=0.02 secs]
[Full GC [CMS[CMS-concurrent-mark: 0.381/0.382 secs] [Times: user=0.39 sys=0.00, real=0.38 secs]
(concurrent mode failure): 81920K->81919K(81920K), 1.0314885 secs] 96703K->96286K(96704K), [CMS Perm : 43687K->43687K(65536K)], 1.0315522 secs] [Times: user=1.03 sys=0.00, real=1.03 secs]

大面积的FULL_GC,而且中途很少有应用日志输出,concurrent mode failure经常性出现,由此可以断定,基本上应用假死是由于[CMS] 退化成stop-the-world的gc方式引起的。

间歇性的OOM:是因为其他线程一直在执行,偶尔报个OOM也是正常的。

问题:为什么STOP-THE-WORLD的时间这么长,执行了将近五分钟执行while(true)的代码才抛出OOM?谁知道呢。。

执行while(true)的线程抛出OOM之后,有一定内存之后,FULL_GC不出现了,应用的部分功能如期的恢复,有个MQ一直报错,看样子也恢复不了了。

问题:为什么服务器假死会导致客户端调用的时候出现No provider异常?是因为dubbo采用zk作为注册中心,注册的时候dubbo向zk创建Ephemeral节点,zk服务器维护了一个会话,在30s收不到ping包的时候判断session失效,session失效意味着Ephemeral节点会被删除,节点删除的时候dubbo客户端会收到节点删除通知,dubbo客户端更新自己本地的可用provider列表(此时无可用provider),所以报了异常。

附jvmGC参数,为什么执行了这么长时间的Full GC主执行while(true)的线程才OOM?:

-XX:+PrintGCDetails
-XX:+DisableExplicitGC
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled -
-XX:+UseCMSCompactAtFullCollection
-XX:LargePageSizeInBytes=128m
-XX:+UseFastAccessorMethods
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=70

你可能感兴趣的:(杂七杂八)