問題排查: spring kafka memory leak

現象: 某個服務上線後,發現運行幾天時間後,就沒有響應了,也沒有日誌輸出。以前的日誌裏面也沒有任何異常。
猜想 : 進程也在,nginx等日誌都正常,數據庫也正常,懷疑就是服務有內存泄露。
排查思路
1. 生產環境不能影響正常服務,出現問題後,運維第一時間作了重啓,現場就沒了。而後用寫了shell先定時重啓(多臺暫不間斷提供服務)。
2. 接下來,就使用jmap看內存的對象數量了,整體來時只增不減的就是有問題的。同時,也作了個單獨的測試環境,運行起來服務,準備重現問題。
3. 如下以重現的測試環境爲例,首先找到進程號(假設是1302)java

(1) 使用 jmap -heap 1302  先看一下堆的狀況
Attaching to process ID 1302, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11nginx

using thread-local object allocation.
Parallel GC with 8 thread(s)git

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 4164943872 (3972.0MB)
   NewSize                  = 87031808 (83.0MB)
   MaxNewSize               = 1388314624 (1324.0MB)
   OldSize                  = 175112192 (167.0MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)github

Heap Usage:
PS Young Generation
Eden Space:
   capacity = 9437184 (9.0MB)
   used     = 9100328 (8.678749084472656MB)
   free     = 336856 (0.32125091552734375MB)
   96.43054538302951% used
From Space:
   capacity = 2621440 (2.5MB)
   used     = 0 (0.0MB)
   free     = 2621440 (2.5MB)
   0.0% used
To Space:
   capacity = 3145728 (3.0MB)
   used     = 0 (0.0MB)
   free     = 3145728 (3.0MB)
   0.0% used
PS Old Generation
   capacity = 2776629248 (2648.0MB)
   used     = 2776562952 (2647.9367752075195MB)
   free     = 66296 (0.06322479248046875MB)
   99.99761235677944% usedspring

26258 interned Strings occupying 3126264 bytes.shell

能夠看到, PS Old Generation的空間已經佔盡了,程序無響應就是這個狀況的直接後果。數據庫

(2) 那就打印一下內存的對象佔用狀況,內容較多,就把內容輸出到一個文本。
jmap -histo -F ${pid} > /xxx/logs/jmap.log apache

內容以下:運維

Attaching to process ID 1302, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11
Object Histogram:jvm

num       #instances    #bytes  Class description
--------------------------------------------------------------------------
1:              7393486 177443664       java.lang.String
2:              3653036 146121440       org.apache.kafka.clients.consumer.ConsumerRecord
3:              3653040 87672960        java.util.concurrent.LinkedBlockingQueue$Node
 

看了一下,ConsumerRecord 數量不少,和業務邏輯不符合(備註:線上環境能夠持續關注這個對象的數量,若是持續的只增長不回收,就要注意了),且不被回收減小。

(3) 去項目程序看,使用這個對象的地方,通過排查,項目程序並沒有引用問題。使用這個對象的地方是,kafka的消費者Listener,對象由spring-kafka提供。因而懷疑是第三方spring kafka的bug。

(4) 經查, 我找到了這個兩個issue。

https://github.com/spring-projects/spring-kafka/pull/162

https://github.com/spring-projects/spring-kafka/issues/161

查看issue的內容, 確認了一下版本號,咱們用的依賴jar, 是在這個issue解決以前的。那這個對咱們有影響,符合邏輯推演。由於咱們的隊列量不大不小,一直不回收,就會有這個問題。

(5) 更新版本,從新上線或測試環境, 觀察heap使用狀況。

參考:

JDK內置工具使用:  http://blog.csdn.net/fenglibing/article/details/6411924

jvm查內存泄漏利器 - jmap: http://www.wujianjun.org/2016/09/21/jvm-tools-jmap/

 

FIXING SUN.JVM.HOTSPOT.DEBUGGER.DEBUGGEREXCEPTION: CAN’T ATTACH TO THE PROCESS: https://zenidas.wordpress.com/recipes/fixing-sun-jvm-hotspot-debugger-debuggerexception-cant-attach-to-the-process/

使用堆外內存:  http://www.raychase.net/1526

相關文章
相關標籤/搜索