問題描述
最近公司的線上監控系統給我推送了一些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(), 美滋滋: