问题排查: spring kafka memory leak

你。 提交于 2019-12-07 09:41:12

现象: 某个服务上线后,发现运行几天时间后,就没有响应了,也没有日志输出。之前的日志里面也没有任何异常。
猜测 : 进程也在,nginx等日志都正常,数据库也正常,怀疑就是服务有内存泄露。
排查思路
1. 生产环境不能影响正常服务,出现问题后,运维第一时间做了重启,现场就没了。然后用写了shell先定时重启(多台暂不间断提供服务)。
2. 接下来,就使用jmap看内存的对象数量了,总体来时只增不减的就是有问题的。同时,也做了个单独的测试环境,运行起来服务,准备重现问题。
3. 以下以重现的测试环境为例,首先找到进程号(假设是1302)

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

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

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)

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% used

26258 interned Strings occupying 3126264 bytes.

可以看到, PS Old Generation的空间已经占尽了,程序无响应就是这个情况的直接后果。

(2) 那就打印一下内存的对象占用情况,内容较多,就把内容输出到一个文本。
jmap -histo -F ${pid} > /xxx/logs/jmap.log 

内容如下:

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

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

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!