前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个kafka的辛酸填坑路

一个kafka的辛酸填坑路

作者头像
柏炎
发布2022-08-23 14:42:39
6580
发布2022-08-23 14:42:39
举报

一.前言

kafka是一个分布式的,支持多分区、多副本,基于 Zookeeper 的分布式消息流平台,它同时也是一款开源的基于发布订阅模式的消息引擎系统

博主所在的部门就是使用kafka做消息中间件,前不久碰到了一个奇奇怪怪的bug,找问题还花了不少功夫,特此在这记录一下。

二.bug起源

我所负责的模块里面有一个功能是修改宿主机的网络ip。

功能页面如下

image-20211027153242806.png
image-20211027153242806.png

输入IPV4地址后,就会将服务所在的宿主机地址给修改掉。

先说一下背景:测试环境所有服务均布在一台机器上,修改ip之后需要同步修改nacos配置中心的配置,各个中间件读取系统环境变量的配置等。然后整机重启,重启完成后,自动启动各个业务应用与中间件的docker容器。

从需求上来看,逻辑实现比较简单,java程序调用shell脚本去做一些宿主机上的操作,然后重启机器就好了。

功能代码咔咔一顿写。

写完之后一测试,ifconfig看一下ip已经修改,docker ps看一下容器都正常启动了,前端页面简单测试一些功能,都正常。

美滋滋啊,我果然是一个代码天才~

提测后,测试小姐姐给我说系统的操作记录一直没有生成,操作记录都是统一拦截发送到kafka,由专门的日志模块去消费记录到es。

淦!这功能也是最近刚开发的,刚刚改完一轮bug,自测过没有问题了。看了看代码,最后一次这个模块的提交记录也是我。

奇怪了。

看一下后台的日志,疯狂打印WARN日志

代码语言:javascript
复制
1 partitions have leader brokers without a matching listener...

我就进到kafka的容器里面看了一下服务的消费情况

代码语言:javascript
复制
kafka-consumer-groups.sh --bootstrap-server 127.0.0.1:9092 --group baiyan-topic --describe

看到消费情况为比较滞后,再去看一下卡主的topic的数据是什么

代码语言:javascript
复制
kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 --topic baiyan-topic --offset 373159  --partition 0 

数据为

代码语言:javascript
复制
{省略业务字段,"createTime":"2021-10-20 16:27:39.447","updateTime":"2021-10-20 16:27:39.447"}

what?

这个时间怎么好像跟我更新测试环境IP的时间这么接近?

大量的消息积压在这个时间点无法被consumer处理到!

三.找问题

3.1.google报错

为了确定这个bug就是修改ip导致的,我让测试小姐姐在另外一台机器上全量模拟安装了一套环境,我又去修改了一下ip,果然又出现了这个问题。

ok,到这里,我们掌握的bug来源或者解决问题的入口就只有两个。

1.报错信息: 1 partitions have leader brokers without a matching listener 2.修改ip: 修改ip后,kafka消息堆积,无法消费,从提示信息来看是分区没有了lead节点导致。

好了,解决bug开始,第一步,google,哈哈哈哈~

在google一顿搜索:1 partitions have leader brokers without a matching listener

网上给出的答案大致集中在:

  1. kafka分区所在的服务器down了,rebalance失败。
  2. 防火墙没有关闭,导致网络不通。
  3. 代理ip配置不正确。
image-20211027165004202.png
image-20211027165004202.png

一个个看

第一点: 看了kafka的容器,启动正常,且如果新增一个topic,也能正常发送与消费,排除!

第二点: 防火墙未开启,哪怕开启了,端口也是通的,排除!

第三点: 从google来看,应该是这个答案了。

看一下配置文件的内容

代码语言:javascript
复制
cat /opt/kafka/config server.properties 

与ip有关系的参数都很正常,已经修改成目标ip值,并且往上搜索到的配置都是注释的

image-20211027165922400.png
image-20211027165922400.png

我们使用的是比较早期的配置

代码语言:javascript
复制
advertised.host.name=目标ip

但是走投无路,我还是抱着试一试心态,按照网上的操作去修改了配置,重启。

结果跟预想的一样,完全没用。

3.2.切换ip入手

一顿google,最后搜索出来的也都是说kafka集群搭建配置与网络问题,与3.1的搜索内容基本一致。

放弃。

3.3.原理入手

当时尝试使用3.1与3.2这两个线索搜索到的信息去解决问题无果后,还是有点难受的。不知道从哪里入手了。

后来想了想,kafka与消费者直接的交互,kafka的集群信息等同步信息,都是维护在zookeeper上的。

好,一个个来,一个个看。

先看一下topic的情况

代码语言:javascript
复制
bash-4.4# kafka-topics.sh  --zookeeper 127.0.0.1:2181 --topic baiyan-topic --describe    
​
Topic: baiyan-topic   PartitionCount: 1       ReplicationFactor: 1    Configs: 
Topic: baiyan-topic   Partition: 0    Leader: none    Replicas: 1001  Isr: 1001

好了,这里发现一个端倪,leader为none,但是并没什么L用,从报错也能看出来。

继续到zookeeper的容器里面看一下kafka的信息

进入到bin目录

1.查看分区情况

代码语言:javascript
复制
ls /brokers/topics/baiyan-topic/partitions
​
[0]

2.查看broker的id情况

代码语言:javascript
复制
ls /brokers/ids
​
[1002]

至此,大家发现一些不一样的地方没有?

zookeeper上broker的id已经变成了1002,但是kafka里面topic信息副本与Isr的节点信息还是1001

kafka需要从zookeeper上获取到broker的节点信息来构建集群,kafka无法在zookeeper上找到1002节点,因此leader为none,无法构建集群。

ok,至此已经知道了导致这个bug出现的原因是什么了~

3.4.原因剖析

3.3.我们已经知道了导致消息阻塞的原因是什么了。那么导致zk与kafka上broker信息不一致的原因是什么呢?

突破口其实也挺清晰的了,broker不一致,那就从决定brokerId生成的几个因素去看一下。

引用一下《深入理解kafka》作者朱小厮大佬的博客:Kafka参数broker.id详解

image-20211027194233996.png
image-20211027194233996.png

由上可知,决定brokerId主要来源于两个文件,server.propertiesmeta.properties

先看一下server.properties配置

image-20211027194453959.png
image-20211027194453959.png

-1则为自动分配,默认配置从1001开始起跳,符合kafka的topic信息为1001。

再看一下meta.properties

存在于server.properties的配置log.dirs目录下,查看配置

代码语言:javascript
复制
cluster.id=uHTKS_74RhW2_wKwbuwHxQ
version=0
broker.id=1002

好家伙,找到问题了!!!!

脚本修改ip后,修改了log.dirs,新生成了一个数据目录。重启kafka后,原先的topic内部的brokerid并未修改。而zk上,只要kafka节点下线了,1001节点数据被抹除,kafka重启后,新的log.dirs的数据目录生成。又因为server.properties上brokerId配置的是-1,由kakfa进行自增,从1001增加到1002,写入到的log.dirs目录下,并将1002节点注册到zk上,最终到了kafka与zk上互相不一致。

四.解决问题

知道了原因之后,解决问题的思路也就很清楚了嘛,只要保证ip修改后,新生成数据目录的brokerId与topic中brokerId保持一致即可。

方法一:

还原新的log.dirs目录下的meta.properties的broker.id属性为1001,在重启kafka,同步1001至zk。

太蠢了,治标不治本,集群模式下都不知道每个节点的id,需要人为介入。

方法二:

每个kafka节点指定server.properties内broker.id的值,不进行动态生成。

五.总结

本文分析kafka在宿主机修改了ip后,consumer无法消费到节点数据的问题。由浅入深的讲述了bug的排查过程。最终定位到broker.id不一致的bug。

我们因为测试环境是单机的,并没有指定broker.id,动态生成id导致了bug。

其实最终解决bug是比较简单的,改一下配置,重启就好了,但是排查过程比较艰辛。

这里回想起面试的时候应该也有不少的面试官会问kafka一些原理性的八股文,回头来想想也不是没有道理。

这里我强烈建议大家在使用的kafka的时候,不论是单节点的kafka还是kafka集群,都指定每个节点的id, 避免出现一些匪夷所思的bug。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-10-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.前言
  • 二.bug起源
  • 三.找问题
    • 3.1.google报错
      • 3.2.切换ip入手
        • 3.3.原理入手
          • 3.4.原因剖析
          • 四.解决问题
          • 五.总结
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档