问题描述
短信报警堆内存GC后依然超过4G内存,跟上篇文章所说情况相同。只是上次情况告警短信没发出来。这次介入前,dump了该节点的堆照,方便定位引起的问题。
告警GC日志,回收后依然在4G内存,回收前后只减少了几百M。
1 | 2019-05-26T20:41:52.086+0800: 12768164.084: [GC pause (G1 Evacuation Pause) (young), 0.0296753 secs] |
堆内存分析
有个对象的内存占用高达2.5G
通过图示可以看到该类:
org.apache.kafka.common.metrics.JmxReporter有个Map,持有高达近330万个的子Map对象。这些子Map中的结构都类似,只是clientId数值不同。
问题:为何消费者注册到该Reporter不删除呢?
代码追踪
JmxReport类分析
下面贴出JmxReporter完整的类,成员变量
1 | private final Map<String, KafkaMbean> mbeans = new HashMap<String, KafkaMbean>();即该mbeans持有330万个子对象。 |
1 | package org.apache.kafka.common.metrics; |
Jconsole查看
kafka.server:type=Request
问题解决
刚开始觉得是我们使用的问题,是否资源没有关闭,查看源代码也未能看出哪里出了问题。
后来确定为kafka 0.11.0.2版本的Bug,在0.11.0.3版本已经修复。
ISSUE
https://issues.apache.org/jira/browse/KAFKA-6199
https://issues.apache.org/jira/browse/KAFKA-6307
两个版本的源码对比 JmxReporter