当前位置: 首页 > Java > 正文

整个集群fgc严重,导致无法为用户提供服务

关键字:
1 星2 星3 星4 星5 星 (暂无评分)
Loading ... Loading ...
baidu_share

现象是:
整个集群fgc严重,导致无法为用户提供服务。

原因分析:
从现象来看,应该是个相当简单的类似内存泄露的问题,模式化的开始了OOM问题排查的过程。

拿到fgc严重时的heap dump进行分析,heap dump显示确实java heap基本被用满了,继续看Dominator tree,惊讶的发现排第一的才占了7%的内存;切换到leakage的视图看,发现有一类型的类占据了超过40%的内存,用GC root跟是什么地方在引用这些类,看到的是很多的http线程在持有这些类的引用;为什么这么多的http线程持有这些类的引用又不释放呢,需要看下这些线程都在做什么,于是切换到thread视图,发现这些http线程中除了一个在run,其他的都在等一把锁,run的那个线程持有了这把锁,继续看run的那个线程那行代码在做什么,发现那是个极为简单的动作,完全不可能运行很久,这样的现象说明是由于某些原因导致这个run的线程一直获取不到cpu资源;翻查当时机器的状况,系统的状况是正常的,但Java应用一直在fgc,连续频繁的fgc导致了上面的那些线程压根就没有执行的机会,在这种情况下这个应用其实已经不可能恢复了。

上面分析了那么多,唯一能得到的结论就是应用本身没有内存泄露,但到底是什么原因触发了应用频繁fgc呢,继续翻查应用的gc log,发现有个现象是在频繁fgc之前cms gc的频率越来越近,并且每次回收后存活的空间占用的越来越大,造成这样的现象是应用的qps增高了太多,或者reponse time(rt)慢了很多造成的,查看应用的qps没什么变化,但应用的rt在cms gc频率变短前有些许的增长,这样基本能解释通:
应用rt增高,导致在cms gc执行的周期内存活的对象增多,于是cms gc频率开始缩短;而cms gc频率缩短,又进一步导致了rt增高,开始形成了恶性循环。

因此说明这个应用在目前的机器数和qps下其实已经到达瓶颈了,稍微的rt或qps的波动都有可能导致整集群崩盘。

在这个结的情况下问题是没法解决的,要解决这个问题只能是提升应用的性能或扩容机器。

case带来的思考:
这种case其实挺折腾的,在以前讲线程池大小的帖子里也写过一次,就是线程池的最大值开的太大的话,看起来是能接更多的请求(如果cpu处理不是瓶颈的话),但不幸的是通常也会导致存活的对象增多,有可能触发gc,而gc的频繁介入很容易导致恶化的现象。

要预防这种case的另外一个更好的做法还是保持一定频率压测获得应用的单机qps能力,并做相应的限流,确保整体qps达到一定的水位后就扩容。

本文固定链接: http://www.chepoo.com/the-whole-cluster-fgc-is-serious-resulting-in-no-service-for-the-user.html | IT技术精华网

整个集群fgc严重,导致无法为用户提供服务:等您坐沙发呢!

发表评论