【Kafka】Leader丢失导致的Consumer挂起故障解决

2024-01-15 10:18

本文主要是介绍【Kafka】Leader丢失导致的Consumer挂起故障解决,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

现象

最近发现线上的Kafka Consumer Client频繁出现无法消费的情况,导致offset积压。但是在重启Kafka Broker之后又正常了。 而Cloudera Manager在重启之前,我们发现三台broker中并没有KakfaController。让人很是不解。

排查步骤

检查Topic的状态

目前已经没办法复现当时的场景,我们简单描述下,通过命令

kafka-topics --zookeeper hadoop02 --desc

检查Topic的状态如下:

782bc1b6bfd430808346ff07a529e90e.jpeg

这张图是后续补的,当时的现象是Leader的值均为-1,Isr的值也均为-1

至此我们猜测是因为KakfaController丢失导致的partition leader为-1,进而导致的Consumer端无法正常消费。

查看Leader的选举方式

在这里我们需要先看下KafkaController,KafkaServer.startup()的时候会新建KafkaController,而KafkaController在启动时,启动了Controller的Elector

def startup() = {inLock(controllerContext.controllerLock) {info("Controller starting up");registerSessionExpirationListener()isRunning = truecontrollerElector.startupinfo("Controller startup complete")}
}

我们再点进去查看下Controller是怎么elect出来的:

def elect: Boolean = {val timestamp = SystemTime.milliseconds.toStringval electString = Json.encode(Map("version" -> 1, "brokerid" -> brokerId, "timestamp" -> timestamp))leaderId = getControllerID /* * We can get here during the initial startup and the handleDeleted ZK callback. Because of the potential race condition, * it's possible that the controller has already been elected when we get here. This check will prevent the following * createEphemeralPath method from getting into an infinite loop if this broker is already the controller.*/if(leaderId != -1) {debug("Broker %d has been elected as leader, so stopping the election process.".format(leaderId))return amILeader}try {createEphemeralPathExpectConflictHandleZKBug(controllerContext.zkClient, electionPath, electString, brokerId,(controllerString : String, leaderId : Any) => KafkaController.parseControllerId(controllerString) == leaderId.asInstanceOf[Int],controllerContext.zkSessionTimeout)info(brokerId + " successfully elected as leader")leaderId = brokerIdonBecomingLeader()} catch {case e: ZkNodeExistsException =>// If someone else has written the path, thenleaderId = getControllerID if (leaderId != -1)debug("Broker %d was elected as leader instead of broker %d".format(leaderId, brokerId))elsewarn("A leader has been elected but just resigned, this will result in another round of election")case e2: Throwable =>error("Error while electing or becoming leader on broker %d".format(brokerId), e2)resign()}amILeader
}

从上面的选举代码中我们可以看出在Kafka集群刚启动时,默认Broker谁先启动则默认为Controller,后续若/controller节点发生变化,会触发Leader变更监听程序LeaderChangeListener,执行变更操作或者重新选举

inLock(controllerContext.controllerLock) {debug("%s leader change listener fired for path %s to handle data deleted: trying to elect as a leader".format(brokerId, dataPath))if(amILeader)onResigningAsLeader()elect
}

我们知道kafka消费的时候需要和Leader通信,而Leader不存在导致的没办法消费很容易理解,那么为什么Controller丢失会导致partition的leader不正常呢?我们来看下面一张图片(图片来自CSDN博主:happy19870612):

040f0b83f53ee92fd89827c6cbacd2f6.jpeg

val replicaStateMachine = new ReplicaStateMachine(this)

我们可以发现Replica的状态机管理是在KafkaController中完成的,也就是说Controller丢失的情况下,也就失去了与Zookeeper交互的能力。默认情况下Leader必须从ISR列表中选择,我们发现列表为空(经过排查发现是Kafka的bug,在Controller和Zookeeper通信过程中出现问题时,可能导致leader丢失而无法通信的情况,这个可能性是很大的,因为zookeeper在高并发环境是容易超时,这就是为什么在kafka 0.8.2.1之后更建议我们使用kafka topic的方式存储offset而不是存储在zookeeper中。

检查系统日志

当然一般情况下我们会先检查系统日志是否有报异常,这种定位问题效率最高。我们来看看kafka的server log是不是有和zookeeper相关的异常
69ccfad49b16247b3a1a81ab80c13c0f.jpeg

从图上可以发现,的确存在zookeeper连接失败的情况,另外我们发现一个比较诡异的事情:

2018-04-10 00:30:11,149 INFO kafka.controller.KafkaController: [Controller 218]: Currently active brokers in the cluster: Set()

所有的broker都临时下线了,然后我查看了其他broker的server log发现所有机器在同一时间均出现了zookeeper连接超时的情况,导致了后续一连串的ERROR:
f5870ae25a2646e6af84d21cf38776f3.jpeg

解决方式

那么问题已经很明了了,我们又检查了下凌晨的网络IO:
d58931ca26e517e1656afa39fad82370.jpeg

发现凌晨的时候出现了流量高峰。可见主要原因还是当时系统IO压力大导致的连接超时,于是我们适当调大了zookeeper.session.timeout.ms=12,再也没有出现过超时的情况。实际上这是kafka的bug,在0.10版本中已经解决了。另一方面在我们集群中出现这个问题,有一部分原因在于,我们的kafka集群和zookeeper集群是在不同的机房,不同的网络中。在后来的排查中我们发现有一台交换机网口有问题导致的带宽不稳定,特别是在大规模计算的时候尤为明显。

PS:当zookeeper服务器端和客户端版本不一致的时候也会导致连接超时的情况。

这篇关于【Kafka】Leader丢失导致的Consumer挂起故障解决的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/608553

相关文章

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

javacv依赖太大导致jar包也大的解决办法

《javacv依赖太大导致jar包也大的解决办法》随着项目的复杂度和依赖关系的增加,打包后的JAR包可能会变得很大,:本文主要介绍javacv依赖太大导致jar包也大的解决办法,文中通过代码介绍的... 目录前言1.检查依赖2.更改依赖3.检查副依赖总结 前言最近在写项目时,用到了Javacv里的获取视频

504 Gateway Timeout网关超时的根源及完美解决方法

《504GatewayTimeout网关超时的根源及完美解决方法》在日常开发和运维过程中,504GatewayTimeout错误是常见的网络问题之一,尤其是在使用反向代理(如Nginx)或... 目录引言为什么会出现 504 错误?1. 探索 504 Gateway Timeout 错误的根源 1.1 后端

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

Java Kafka消费者实现过程

《JavaKafka消费者实现过程》Kafka消费者通过KafkaConsumer类实现,核心机制包括偏移量管理、消费者组协调、批量拉取消息及多线程处理,手动提交offset确保数据可靠性,自动提交... 目录基础KafkaConsumer类分析关键代码与核心算法2.1 订阅与分区分配2.2 拉取消息2.3

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁

Python利用PySpark和Kafka实现流处理引擎构建指南

《Python利用PySpark和Kafka实现流处理引擎构建指南》本文将深入解剖基于Python的实时处理黄金组合:Kafka(分布式消息队列)与PySpark(分布式计算引擎)的化学反应,并构建一... 目录引言:数据洪流时代的生存法则第一章 Kafka:数据世界的中央神经系统消息引擎核心设计哲学高吞吐