生产环境三个服务分别消费kafka(version 1.1.0)不同topic里的日志分析结果,将其写入HBase,其中消费kafka使用的是consumer的subscribe API。服务稳定运行了几个月,某次因为HBase升级将其临时关闭,在重新启动过程中,诡异的问题发生了。
现象
三个服务中有一个可以正常启动,另外两个在启动过程中似乎卡在某个地方block住。打开info级别的日志,发现如下可疑信息
> 2018-12-28 16:58:22 WARN pool-1-thread-2 org.apache.kafka.clients.NetworkClient - [Consumer clientId=consumer-2, groupId=defy-rtlog-receiver-srcproxy] Connection to node -2 could not be established. Broker may not be available.
调整日志级别为debug,重新观察观察日志,发现服务不停打印如下信息
> Coordinator discovery failed, refreshing metadata
分析问题
从日志来看,服务中kafka consumer一直死循环寻找coordinator. 但coordinator是什么鬼?
话说源码之前了无秘密,翻下源码,可以从注释中可以看到GroupCoordinator角色的描述如下
即GroupCoordinator负责管理group的offset,每一个broker启动一个GroupCoordinator,负责管理一些consumer groups。
既然每一个broker都有一个GroupCoordinator,那么如何判断一个group归哪个GroupCoordinator来管呢?
这里涉及到kafka内部一个特殊的topic __consumer_offsets,其用于存储group的消费情况,默认有50个partition。
某一group消费情况要存在哪一个partition,通过以下方式得到def partitionFor(groupId: String): Int = Utils.abs(groupId.hashCode) % groupMetadataTopicPartitionCount
计算得到的partition的leader所在的Broker即为该group