CMAK 解析 Kafka 信息失败的问题分析

问题现象

SRE收到了磁盘空间占用告警,但该服务器主要运行控制服务,很少产生持久化数据,查看了Grafana,也确认是近期磁盘占用率涨的飞快。

CMAK 解析 Kafka 信息失败的问题分析

进入服务器检查,发现是Kafka Manager产生了大量的容器日志,配置了容器stdout/stderrmax-size后,日志得到收缩,告警解除。接着分析大量刷新日志的原因,发现是不断报错无法解析固定一个Kafka集群的消息。

CMAK 解析 Kafka 信息失败的问题分析

其他录入的集群都没有出现这种日志,单单只有一个集群出现,随即检查了对应Kafka集群的指标,发现生产和消费都是正常的,Zookeeper内的元数据也没有出现紊乱,并且核对过版本,跟录入到Kafka Manager的版本号是一致的。
这里可能跟Kafka自身的问题无关了,至于为何单独这个集群出现,我们慢慢定位。

分析过程

owned_partitions应该是Kafka的内部属性,并且需要从topic解析,那么推测应该是从__consumer_offsets里消费的,因为开启了消费监听后,Kafka Manager会通过监听这个内部topic来获取消费者组的消费进度,使用的消费组名称为KMOffsetCache-<id>,于是查看这个Consumer Group的消费情况。

CMAK 解析 Kafka 信息失败的问题分析

有client连接消费,数据也确实是从该Kafka集群获取的,针对该client,进行抓包看看。

# ${kafka-manager-host} 为 Kafka Manager 的主机 IP
tcpdump -i bond0 host ${kafka-manager-host} and port 9092 -t -n -vv -w /tmp/kafka.1.cap

对Kafka协议进行TCP追踪发现,出现大量的关于某个Consumer Group的记录。

CMAK 解析 Kafka 信息失败的问题分析

统计发现,这些Kafka Fetch请求都是消费__consumer_offsets的36号分区,因为__consumer_offsets的分区是根据Group ID的哈希取模得到,意味着这些都来自于同一个Consumer Group ID。

CMAK 解析 Kafka 信息失败的问题分析

查看Kafka Fetch Response的响应报文,倒没有错误记录,但是Message SetRecord Batch里只有1个条目,看上去Consumer Group没有持续消费的动作。

CMAK 解析 Kafka 信息失败的问题分析

因为报文里可以分析出对应的Consumer Group名称,尝试查看消费的情况。

CMAK 解析 Kafka 信息失败的问题分析

这个组在不断的rebalance或者断开连接,非常怪异。但是到这里,已经能猜到大概是什么原因导致Kafka Manager产生频繁的错误日志了。既然一直尝试加入消费或者退出消费,那就直接从Group Coordinator进行抓包分析,首先获取到此Group的Group Coordinator所在broker。

CMAK 解析 Kafka 信息失败的问题分析

然后再到服务器上面进行抓包,抓包命令参考上面的tcpdump即可。将报文在Wireshark上过滤出一份会话进行分析,总的协议交互如下。

CMAK 解析 Kafka 信息失败的问题分析

首先完成了Kafka JoinGroup的交互,这个时候,注册了Consumer Group,并且将Group ID进行哈希后分配到__consumer_offsets对应的Partition来记录,这里就是刚才定位到的36号分区的由来。
紧接着,Kafka Metadata里开始注册Topic来消费。

CMAK 解析 Kafka 信息失败的问题分析

但是集群内并没有这些分区,broker也回包说明了ErrorCode 3(Unknown Topic or Partition),并且后续Consumer Group进行OffsetFetch也返回了空的Topic和Partition。

CMAK 解析 Kafka 信息失败的问题分析

而因为加入阶段,会记录到__consumer_offsets,这也意味着会被Kafka Manager消费到记录,因为没有对应的Topic或Partition,__consumer_offsets的Value内的字节序里没有topic_sizepartition_id的存储,因此在反序列化时,出现了java.nio.BufferUnderflowException的错误。而接入的Client因为代码重试逻辑不断的发起请求,频繁地重复执行上述过程,导致刷新了大量的错误日志,最终影响磁盘使用。

为了验证,可以分析一下message。
上面是正常的Consumer Group的记录,可以看到记录了Topic,解析Value可以获得Partition ID。但是下面异常的,只记录了JoinGroup的记录,并没有消费的目标信息,这也与推测的结果一致。

CMAK 解析 Kafka 信息失败的问题分析

处理结果

Kafka JoinGroup Request里可以获取Client对应的IP来源,找到相关的服务进行修复后,日志也停止了疯狂报错。

针对这类问题,可以通过加入ACL的方式来拦截一些外部项目的胡乱接入。而对容器的日志,也统一设置max-size滚动,避免大量占据日志目录,影响其他服务写入日志。

原文始发于微信公众号(AcidPool):CMAK 解析 Kafka 信息失败的问题分析

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/171018.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!