《Kafka分区阻塞问题的分析和优化分析.docx》由会员分享,可在线阅读,更多相关《Kafka分区阻塞问题的分析和优化分析.docx(10页珍藏版)》请在第一文库网上搜索。
1、Kafka分区阻塞问题的分析和优化分析一、问题描述某日由于Kafka生产环境一个节点出现坏盘,在下班后进行停机更换,更换完成后启动该节点Broker3,某项目组反馈其TopicXXX的第一个分区在十几分钟内无法生产和消费,报Not1eaderForPartition的错误,但是其他分区在该时间段内均可正常生产和消费,出现问题的分区优先级副本是在Broker3上。二、原因分析当天晚上唯一的变更就是Broker3的停机和拉起,而发生问题的分区优先级副本在Broker3上,在日志中我们发现发生问题的时间段内发生了多次1eader副本切换的日志,因此该问题原因定位在Broker拉起后副本重新选举造成的
2、问题。由于生产配置的参数auto.1eader,reba1ance,enab1e为true,Contro11er就会每五分钟检查一下集群不平衡的状态,如果Broker上非优先级副本占全1eader副本回切,回切的过程主要是Contro11er发起优先级副本选举,分区TopicXXX-I的1eader副本由Broker8变成Broker3(修改ZK信息),然后Contro11er告知所有Broker副本变成3,在Broker收到该请求后更新本地的元数据缓存。回切过程中客户端被阻塞,会报类似Not1eaderForPartition的异常,但是按正常情况,该回切应该1分钟内可以完成,不应该会阻塞客
3、户端15分钟这么久。接下来我们分析下当天晚上的日志:Broker3上缓存的步Contro11erTopicXXX-I1eader(以ZK为元数据(标红部分时间点骤日志准)表示和ZK上不一致)117:32:46Broker3Broker3加1eaderEPoCh=426217:57:541eaderEpoch=4261eader=8回1eader=81eaderEpoch=426318:01:18Broker31eaderEpoch=4271eader=81eader=8但是Broker3其实Broker3加没有收到这个请求418:01:291eaderEpoch=4271eader=8回1ea
4、derEPoCh=4261eader=8步骤时间点Contro11erTopicXXX-I1eader(以ZK为元数据(标红部分表示和ZK上不一致)日志准)1eaderEpoch-4281eader-30志里显示comp1etedpreferred1eaderEpoch=426518:02:00副本回切rep1ica1eadere1ection.New1eaderis3.但是Broker3其实没有收到这个请求1eader=81eaderEpoch=4266718:02:1818:02:35Broker3Broker3加回1eaderEpoch=4291eader=81eaderEpoch=42
5、91eader-81eaderEpoch=4301eader=3同1eader-81eaderEpoch-4261eader-81eaderEpoch=426818:07:00副本回切上次18:02一样,Broker3其实没收到该请求1eader=81eaderEpoch=426918:15:32Broker31eaderEpoch=4311eader=81eader=8Broker3加1eaderEpoch-4261018:15:331eaderEpoch=4321eader-81eader-8步时间点骤Contro11erTopicXXX-I1eader(以ZK为元数据(标红部分日志准)表
6、示和ZK上不一致)1eaderEpoch-4331eader-3同1eaderEPoCh=4261118:17:00副本回切前,Broker3其实没收到该请求1eader=81eaderEpoch=4261218:27:28Broker31eaderEpoch=4341eader=81eader=8Broker3加1eaderEPOCh=4261318:27:291eaderEpoch=4341eader=8回1eader=81eaderEpoch=4261418:32:00副本回切1eaderEPOCh=4351eader-31eader=8Broker3刚接到1eaderEpoch=434
7、1eader=8的更新请1518:38:39无变化1eaderEpoch=4351eader=3求1eaderEpoch=4341eader=8根据上述日志,我们发现,Broker3在拉起后,发生了4次失联(与ZK的会话超时),同时叠加3次副本回切,这期间除Broker3外,其他Broker均能正常收到Contro11er发出的1eaderAndIsr和UpdateMetadataRequest,而Broker3在18:02之后没有收到1eaderEPOCh从427到433的更新请求,一直到18:38分才收到1eaderEPOCh=434的信息,在18:54分收到1eaderEpoch=435
8、信息O在18:32-18:54之间,Broker3上缓存的1eader是指向Broker8,而其他Broker上缓存的1eader是指向Broker3,假设客户端从Broker3拿到元数据后往1eaderBroker8发送数据,而Broker8认为自己不是1eader,就会给客户端返回Not1eaderForPartition的错误;而假设客户端从Broker8上拿到元数据后往1eaderBroker3发送数据,而Broker3认为自己不是1eader,同样会给客户端返回错误,那么这段时间内客户端是找不到1eader的,一直到18:54分,BrOker3和大家同步了元数据后,客户端才恢复正常。
9、这种异常会发生在上述表格中多处,只要是BrC)ker3保存的元数据和其他BrC)ker不一致,就会有这个问题。也就是说,这次问题主要是Broker3和其他Broker保存的元数据不一致导致的,而Broker3在18:02分之后为什么没有收到来自Contro11er的多个元数据更新请求,我们在日志中发现BrOker3上大量的thereisnoopenconnection,的Warning信息。根据监控数据来看,从18:00至18:10,Broker3上TCP连接数暴涨到将近3万,这大量的连接是从哪里来的呢,正常运行的情况下单个BrOker只有1万个连接?这就要从客户端与服务器的连接原理来分析,从
10、在18:02分左右副本回切,客户端从其他BrOker上得知分区1eader在BrOker3上,从而连接Broker3拉取元数据或者数据,但是Broker3上缓存的1eader不是自己(拉起后同步数据负载较高,未及时处理COntrO1Ier发来的请求),返回给客户端Not1eaderForPartition的错误,客户端会再次连BrOker3(客户端优先连已连过的Broker)强制刷新获取元数据,大量客户端请求叠加就造成了网络风暴。另外,在Kafka11版本上,BrOker处理请求的时候,是不区分请求的优先级的,对于Contro11er发过来的更新元数据的请求和客户端发过来的数据请求都是放在同一
11、个队列里的,大量客户端的请求排在队列里BrOker3的请求队列里,导致Broker3无法及时处理ControIIer发来的更新元数据的请求。因此造成了Broker3和其他服务器上保存的元数据不一致。总的来说,该生产问题主要是BrOker3拉起后同步数据负载较大,再叠加18:02分副本回切未及时更新元数据,导致Broker3和其他Broker缓存的元数据不一致,而目前Kafka的设计是无法优先处理来自Contro11er的更新类控制请求,导致集群内在较长一段时间窗口范围内各Broker元数据处于不一致的状杰,从而造成部分分区上生产或消费较长时间的阻塞。三、优化方案1关闭优先级副本回切当优先级副本
12、回切开启时,auto,1eader,reba1ance,enab1e设置的是默认值true,ContrOIIer就会每五分钟(默认)检查一下集群不平衡的状态,如果BrOker上非优先级副本占全部副本数的10%,那么会进行重新平衡。该参数设置为true的好处是,在Broker挂了之后,分布其上的1eader副本就会自动切换到其他活着的broker上,在挂掉的Broker重启之后,集群会将他之前的Ieader副本再切换回来,从而维持整个集群的1eader副本均衡,不需要运维人员手工维护。但是每做一次副本选举代价较高(COntrOI1er选举新1eader,大量更新ZK,广播给其他BrOker,老1
13、eader切换成FOIIOWer去新的1eader同步数据,客户端发现1eader切换后发起新的元数据请求等),会阻塞客户端。尤其是在分区数多,客户端多的高负载集群上,副本切换的代价更高。当关闭优先级副本回切后,Broker3在拉起过程中,上面所有的分区一直都是fo11ower,客户端不会往BrOker3上写入或消费,不会出现新建会话激增的情况,可以避免像生产问题的出现,在Broker3拉起同步数据后,我们在业务低峰期用Conf1uent提供的kafka-Preferred-rep1ica-e1ection脚本进行副本回切,保持整个集群的1eader副本均衡。2 .增大请求队列大小在问题分析过
14、程中,我们发现Broker3没有收到来自Contro11er的控制请求,而目前每个Broker上1eader副本有1000多个,假设在极端时刻,客户端在同一时间往所有的1eader副本发起请求,那么目前请求队列的大小(queued.max.request=500)不够缓存这么多请求,因此我们将该请求队列的大小调大至IOOOo3 .增加请求队列的相关监控在本次问题中,Broker3未及时处理来自COntrOI1er的请求,我们发现监控里也缺少Broker上请求相关的监控,因此我们增加了以下监控项便于以后问题分析和调优:监控项说明具体JMX指标ProducerBroker上每秒产生的kafka.s
15、erver:type=BrokerTopicMetrics,name=FaiIedPro请求失败Produce请求失败的duceRequestsPerSec数数量Broker上每秒产生的Fetch请kafka.server:type=BrokerTopicMetrics,name=FaiIedFetFeteh请求失败的数求失败数ChRequestsPerSec量Broker上请求队列work:type-RequestChanne1,name-RequestQueueRequestChanne1中请大小Size求个数响应队列work:type=RequestChanne1,name=ResponseQueu响应队列大小大小eSize请求处理work:type=RequestMetrics,name=Tota1TimeMs,请求被处理的总时间时间request-(ProduceFetchConsumerFetch