作者:Vivo Internet Server Team-Luo Mingbo
为了使读者能够更好地与小小比的关注问题产生共鸣,我首先与读者和朋友保持一致,以与我们的Kafka群集的部署架构和服务保持一致,以访问Kafka群集。
为了避免大规模群集,我们根据业务维度按照多个KAFKA簇进行了整个Kafka群集,负责整个10万亿个新闻。集群太大。由于交通突变,资源隔离,速度限制和其他原因引起的集群稳定性和可用性很容易。抵抗风险少于紧急情况的能力较小。
由于KAFKA数据存储和服务在同一节点上具有较长的集群扩展周期,因此我们在遇到突然流量时无法快速实现集群扩展并承受业务压力,因此我们遵循业务维度和数据的程度以及它是否影响商业化。kafka群集分开,并在Kafka群集中添加一层逻辑概念“资源组”。资源组中的节点节点共享与资源组和资源组之间的节点资源分离,以确保发生故障。它将带来雪崩效应。
我认为,通过引入上述架构部署和访问过程,许多相关的知识点与编辑者保持一致。
从部署体系结构图中,我们可以清楚地理解我们的群集以最小的资源隔离单元作为“资源组”部署在服务器上,也就是说,在同一资源组下的多个代理节点之间会产生效果。节点是逻辑隔离。
上述的相关知识点对齐后我们将开启我们的故障排查之旅。
故障发生时,故障节点所在资源组的多个 topic 流量几乎全部掉零,生产环境我们对 Kafka 集群的磁盘指标READ、WRITE、IO.UTIL、AVG.WAIT、READ.REQ、WRITE.REQ做了告警监控,由于故障发生在凌晨,整个故障的处理过程持续实践较长,导致了业务方长时间的topic流量整体掉零对业务造成不小的影响。
1、故障节点在故障发生时网络空闲率出现短暂的掉零情况,且与生产流量监控指标一致。一旦生产流量上升故障节点的网络空闲率就同步掉零。
2、Grafana 监控指标中topic生产流量几乎全部掉零。
3、Kafka 平台项目监控中也体现了当前项目的多个topic生产流量指标掉零。
SDF 盘的IO.UTIL指标达到100%, 80%左右我们认为是服务可稳定运行的指标阈值。
SDF 盘的AVG.WAIT指标达到分钟级等待,一般400ms左右的延迟我们认为是服务可稳定运行的阈值。
Kafka集群controller节点的日志中出现Input/Output error的错误日志。
Linux 系统日志中出现Buffer I/O error 的错误日志
从上述的指标监控中很明显的可以得出结论,故障原因是由于 Kafka broker节点的sdf盘磁盘故障导致的,只需在对应的 Kafka broker 节点上将sdf盘踢掉重启即可恢复。那这样就结束了吗 ?of course not。
对 Kafka 有一定认识的小伙伴应该都知道,创建topic时topic的分区是均匀分布到集群内的不同broker节点上的,即使内部某一台broker节点故障,其他分区应该能正常进行生产消费,如果其他分区能进行正常的生产和消费就不应该出现整个topic的流量几乎全掉零的情况。
如上图所示,topicA 的三个分区分别分布在 brokerA、brokerB、brokerC三个物理主机节点上。
生产者producer向TopicA发送消息时会分别与brokerA、brokerB、brokerC三个物理主机节点建立长链接进行消息的发送,此时若 brokerB 节点发生故障无法向外部提供服务时按照我们的猜想应该不会影响到brokerA和brokerC两个节点继续向producer提供接收消息的服务。
但从监控指标的数据展示来分析当brokerB节点出现故障后topic整体流量掉零与我们的猜想大相径庭。
既然是出现类似了服务雪崩的效应导致了部分topic的整体流量几乎掉零那么我们在猜想问题发生的原因时就可以往资源隔离的方向去思考,看看在整个过程中还有哪些地方涉及到资源隔离的环节进行猜想。
Kafka 服务端我们按照资源组的方式做了 Kafka broker的逻辑隔离且从Grafana监控上可以看出有一些topic的流量并没有严重掉零的情况,那么我们暂时将分析问题的目光转移到 Kafka client端,去分析 Kafka producer的发送消息的过程是否存在有资源隔离地方没有做隔离导致了整体的雪崩效应。
对 Kafka 生产流程流程有一定了解的同学肯定知道,Kafka 作为了大数据生态中海量数据的消息中间件,为了解决海量数据的并发问题 Kafka 在设计之初就采用了客户端缓冲消息,当消息达到一定批量时再进行批量消息的发送。
通过一次网络IO将批量的数据发送到 Kafka 服务端。关于Kafka producer客户端缓冲区的设计小编后续会单独一个篇幅进行深入的探索,鉴于篇幅问题不再此处进行详细分析。
基于此处的分析我们对一批消息发送到一个故障节点时的容错方案可以有以下猜想:
上述猜想中,如果是第一种情况,那么每次消息路由只路由到健康的节点上不会出现雪崩效应耗尽客户端缓冲区资源的情况;
第二种情况,当消息路由到故障节点上时,直接拒绝分配缓冲区资源也不会造成雪崩效应;
第三种情况,每次需要在一个或多个超时时间后才能将故障节点所占用的客户端缓冲区资源释放,在海量消息发送的场景下一个超时时间周期内故障节点上的消息足以将客户端缓冲区资源耗尽,导致其他可用分区无法分配客户端缓冲区资源导致出现雪崩效应。
带着上述的猜想打开Kafka client producer的源代码分析下defaultPartitioner的分区规则得到如下的分配逻辑:
关于这系列的问题思考与分析,我们将在后续的文章中讲述,敬请关注。
原文:https://juejin.cn/post/7100736694978084895