笔者在双十一期间负责的kafka集群的响应时间飙升到了10~30s,严峻影响动静的写入。

通过对日记阐发发现存在大面积分区Leader选举,__consumer_offsets主题的分区也大量停止分区Leader选举,从而招致动静发送几乎停行,大量消费组触发重平衡,整个集群接近瘫痪,最末确定了根因:Broker节点与Zookeeper会话超时,触发大量分区从头选举。
本文借此毛病,与各人一路分析一下Zookeeper在Kafka中起了哪些感化,以及确定“首恶祸首”的过程,希望给各人排盘问题能带来必然的启发。
2、Zookeeper在Kafka中具有无足轻重的感化在正式进入毛病阐发之前,我们起首介绍一下Zookeeper在kafka架构设想中所起的角色。
核心理念:kafka的设想者看待Zookeeper的利用长短常隆重的,即需要依靠Zookeeper停止控造器选举,Broker节点毛病实时发现,但又尽量降低对Zookeeper的依赖。
基于Zookeeper停止的法式开发,我们一般能够通过查看zookeeper中的目次规划,能够窥探出哪些功用是依靠Zookeeper完成,Kafka在Zookeeper中的存储目次构造如下图所示:

上述各个节点,其背后都联系关系着Kafka一个核心工做机造,各人能够顺藤摸瓜停止探究,本文需要重点介绍/brokers那个目次的规划与感化,目次详情如下:

/controller Kafka控造器的信息,Kafka控造器的选举依靠zookeeper。
/brokers/ids/{id} 在耐久节点/brokers/ids下创建浩瀚的临时节点,每一个节点,暗示一个Broker节点,节点的内容存储了Broker的根本信息,例如端口、版本、监听地址等。
/brokers/topics/{topic}/partitions/{partition}/state
在kafka2.8版本一下,Kafka中topic中的路由信息最末耐久化在zookeeper中,每一个broker节点启动后会在内存中缓存一份数据。/brokers节点每一个子节点暗示一个详细的主题,主题的元数据次要包罗分区的个数与每一个分区的形态信息。每一个分区的形态信息次要包罗:
controller_epoch 当前集群控造器的epoch,暗示controller选举的次数,我们能够理解为controller的“版本号”。leader 当前分区Leader所在的broker id。Leader_epoch 分区的leader_epoch,暗示分区Leader选举的次数,从0起头,每发作一次分区leader选举该值就会加一,kafka通过引入leader epoch机造处理低版本依靠依赖水位线暗示副本进度可能形成的数据丧失与数据纷歧致问题,那个将在后续文章中深切分析。isr 分区的isr集合。version 存储形态分区形态数据构造的版本号,那个字段各人能够忽略在Zookeeper中有一种同样的“设想形式”,就是能够通过在zookeeper中创建临时节点+事务监听机造,从而实现数据的实时动态感知,以/brokers/ids为例停止论述:
Kafka broker历程启动时会向zookeeper创建一个临时节点/brokers/ids/{id},此中id为broker的编号
Kafka Broker历程停行后,创建的临时节点在broker与zookeeper的会话超时后会被主动删除,产生节点删除事务
Kafka controller 会主动监听/brokers/ids 目次的节点新增与删除事务,一旦broker下线、上线,controller城市实时感知,从而采纳需要处置。
颠末上面的初步介绍,Kafka对zookeeper的依赖仍是十分大的,出格是Kafka控造器的选举、broker节点的存活形态等都依赖zookeeper。
Kafka 控造器能够看出是整个kafka集群的“大脑”,若是它呈现异动,其影响范畴之广,影响水平之大可想而知,接下来的毛病阐发会给出更曲不雅的展示。
温馨提醒:本文次要是一个毛病阐发过程,后续关于kafka控造器若何选举、leader_epoch副本同步机造等会在《Kafka原理与实战》专栏中逐个介绍,敬请存眷。
3、问题阐发一看到动静发送响应时间长,我的第一反响是查看线程栈,是不是有锁阻塞,但查看线程仓库发现Kafka用于处置恳求的线程池大部门都阻塞在获取使命处,表白“无活可干”形态:
申明客户端端动静发送恳求都没有抵达Kafka的列队队列,而且专门用于处置收集读写的线程池也很空闲,那又是为什么呢?动静发送端延迟超等高,但办事端线程又极度空闲,有点诡异?
继续查看办事端日记,发现了大量主题(以至连络统主题__consumer_offsets主题也发作了Leader选举),日记如下:

核心日记:start at Leader Epoch 大量分区在停止Leader选举。
Kafka中中只要Leader分区能处置读、写恳求,follower分区只是从leader分区复造数据,在Leader节点宕机后参与leader选举,故分区在停止Leader选举时无法处置客户端的写入恳求,而发送端又有重试机造,故动静发送延迟很大。
那到底在什么情况下会触发大量主题停止从头选举呢?
我们找到当前集群的Controler节点,查看state-change.log中,发现如下日记:

呈现了大量分区的形态从OnlinePartition变动为OfflinePartition。
温馨提醒:按照日记我们能够去查看源码,找到输出那些办法的挪用链,就能够顺藤摸瓜去找针对性的日记。
继续查看Controler节点下的controller.log中发现关键日记:

核心日记解读:
[Controller id=1] Broker failure callback for 8 (kafka.controller.KafkaController) 控造器将节点8从集群的在线中移除,控造器为什么会将节点8移除呢?接下来顺藤摸瓜,去看一下节点8上的日记如下图所示:

核心日记解读:本来broker与zookeeper的会话超时,招致临时节点被移除。
先不探究会话为什么会超时,我们先来看一下会话超时,会给Kafka集群带来什么严峻影响。
/brokers/ids下肆意一个节点被删除,Kafka控造器都能及时得到,并施行对应的处置。
那里需要分两种情况考虑。
3.1 通俗Broker节点被移除处置入口为:KafkaController的onBrokerFailure办法,代码详情如下图所示:

一个通俗的broker在zk中被移除,Kafka控造器会将该节点上分配的所有分区的形态从OnlinePartition变动为OfflinePartition,从而触发分区的从头选举。
扩展常识点:__consumer_offsets分区若是停止Leader从头选举,大面积的消费组会触发重平衡,背后的机造:
消费组需要在Broker端停止组协调器选举,选举算法如下:消费组的名称的hashcode与主题 __ consumer_offsets的队列总数取模,取余数,映射成 __consumer_offsets 分区,该分区的leader在哪个broker节点,该节点则会充任消费组的组协调器。
一旦该分区的Leader发作变革,对应的消费组必需从头选举新的组协调器,从而触发消费组的重平衡。
3.2 Controller节点被移除若是zookeeper中移除的broker id 为 Kafka controller,其影响会更大,次要的入口如下图所示:

若是是controller节点会话超时,临时节点/controller节点会被删除,从而会触发Kafka controller选举,最末所有的broker节点城市收到节点/controller的删除、新增或节点数据变革的通知,KafkaController的onControllerFailover办法会被施行,与会将于zookeeper相关的事务监听重视新注册、分区形态机、副本形态机城市停行并从头启动,各个分区会触发主动leader分区选举。
能够如许描述:一朝天子一朝臣,全数从头来过。
3.3 zookeeper会话超时根因排查查看办事端日记,能够看到如下日记:

核心日记解读:Closed socket connection for client ... 暗示毗连被客户端主动封闭。
那为什么客户端会主动封闭心跳呢?心跳处置的套路就是客户端需要按时向办事端发送心跳包,办事端在指按时间内没有收到或处置心跳包,则会超时。
要想一探事实,独一的法子:阅读源码 ,通过研读Zookeeper客户端源码,发现存在如许一个设想:客户端会把所有的恳求先放入一个队列中,然后通过一个发送线程(SendThread)从队列中获取恳求,发送到办事端,关键代码如下:

若是存在大量的zk更新操做,心跳包可能会处置不及时,而在呈现zookeeper session会话超时之前,集群在大面积ISR扩张与收缩,频繁更新zk,从而触发了客户端端心跳超时,那个问题也能够通过如下代码停止复现:

颠末那波阐发,因为zookeeper会话超时,招致大量分区从头选举,最末招致动静发送延迟很大,而且消费组大面积重平衡的底子原因就排查清晰了,本期分享就到此为行,我们下期见。







还没有评论,来说两句吧...