一次频繁Full GC的排查过程

问题描述
最近公司的线上监控系统给我推送了一些kafka lag持续增加的消息,我上生产环境去看了相应的consumer的状况,发现几台机器虽然还在处理消息,可是速度明显慢了不少。node

问题猜想与验证
我猜想是JVM频繁作Full GC,致使进程也跟着频繁卡顿,处理消息的速度天然就慢了。为了验证这个想法,先用jstat看看内存使用状况:git

jstat -gcutil 1 1000 #1是进程号github

结果如我所料,几乎1秒钟就要作一次FGC,能安安静静的作个正常的consumer才有鬼了。缓存

赶忙留了一台consumer拿来作分析,把别的几台consumer都重启。无论怎样,先恢复消费能力再说!网络

内存泄露root cause排查
1秒一次FGC,那确定是发生内存泄露了。this

二话不说,把堆dump下来先!阿里云

jmap -F -dump:format=b,file=heapDump 1 #1是进程号.net

生成的heapDump文件有将近2个G的大小,这么大个文件,为了避免影响生产环境的机器,仍是scp到本地进行分析吧!3d

jhat了一下,直接卡在那里不动了。没办法,祭出VisualVM来帮忙。导入文件以后,发现有一大堆HashMap的Node在那占着:orm

然而并不知道这是个啥,点进去看看内容,发现有一大堆node的key类型是X509CertImpl:

这时候我意识到,问题可能出在网络链接上面。可是仍是无法定位到具体的代码。

没办法,接着向上找线索。不断地经过OQL查询Referrers:

接着查询:

接着查询:

这时候看到了链接池的踪影,感受离真相不远了! 


到了这里,我内心大概知道了答案:问题必定出在阿里云OSS身上。再结合这张图:

就能够猜出是由于使用了OSS的客户端,可是没有正确的释放资源,致使client被回收时,它所建立的资源由于还有别的referrer, 却没有被回收。

再去oss github上的sample一看,果真有这么一段:

而这个shutdown方法作的正是释放Idle资源的事儿:

public void shutdown() {         IdleConnectionReaper.removeConnectionManager(this.connectionManager);         this.connectionManager.shutdown();  } 1 2 3 4 问题修复 知道了缘由,修复也是很轻松的事儿。 在建立client的缓存里加个removeListener,用来主动调用client.shutdown(), 美滋滋:

相关文章
相关标签/搜索