kafka的controlled shutdown请求

这是我的第101篇原创文章
【背景】
kafka基于k8s容器化部署后 , 对容器设置了存活探针 , 即检测监听端口是否存在 。然而一次kill kafka进程的操作 , 服务的重启时间(会自动再拉起kafka进程)超过了存活探针的监测时间 , 导致pod重启 。本文就该问题展开进行分析 。
【kill背后的逻辑】
对于以信号(不带参数的默认发送信号)进行的kill操作 , kafka 会捕获该信号 , 进行服务停止的相关处理动作 , 其中比较重要的两个动作为:
1)
这一步的具体流程包括:
a. 待停止的节点向zk(2.8.0以前版本)获取节点的信息
b. 向建立连接并发送请求 , 

kafka的controlled shutdown请求

文章插图
c. 收到请求后 , 对位于该上的分区进行必要的迁移动作 , 即分区副本数大于1 , 且有存活的其他节点中选出新的 , 然后发送请求通知被选中的成为新的分区;对待停止的上处于状态的分区以rpc请求形式告知停止进行fetch动作 。
d. 最后给待停止的节点进行请求响应 。
之所以要这么做 , 是可以将分区不可服务的时间缩短为毫秒级别 。否则 , zk需要一段时间才能感知到该节点的离线 , 而的监听了对应znode目录的变化 , 因此感知的离线后才触发进行相应的处理动作 , 在未感知到其他节点离线的这段时间内 , 位于停止的节点上的分区是不可服务的 , 因此不可服务时间基本上就取决于kafka与zk之间连接的超时时长 。
2)关闭所有打开的日志文件 , 并创建相关文件以标记文件是正常关闭 。
关闭所有打开的文件 , 并在目录中写入"."文件 。在启动后 , 加载时 , 会判断是否存在"."文件 , 从而决定是否需要进行日志的恢复动作(这里暂不展开) 。
这种关闭服务的方式被称之为优雅的关闭服务 , 而不是kill -9强行结束 。在官方文档中 , 也有相关的介绍 。
另外 , "kafka--stop.sh"脚本本质上也是这么操作的 。
SIGNAL=${SIGNAL:-TERM}PIDS=$(ps ax | grep -i 'kafka\.Kafka' | grep java | grep -v grep | awk '{print $1}')if [ -z "$PIDS" ]; thenecho "No kafka server to stop"exit 1elsekill -s $SIGNAL $PIDSfi
kafka的controlled shutdown请求

文章插图
正常情况下 ,  这个操作都是非常快的 。但是由于该操作细化后的各个步骤都会涉及网络的交互 , 那么 , 在一些异常情况下 , 比如与zk的tcp连接异常、与的网络连接异常、触发的分区重新选举异常等 , 这都会导致请求的重试 , 直到请求成功或者达到最大重试次数才结束 , 这时 , 请求的整体耗时可能会超过30s , 甚至更长 。这也是我们业务中导致pod重启的原因 。
[2023-04-10 14:18:03,597] INFO [KafkaServer id=1] shutting down (kafka.server.KafkaServer)[2023-04-10 14:18:03,599] INFO [KafkaServer id=1] Starting controlled shutdown (kafka.server.KafkaServer)[2023-04-10 14:18:11,010] WARN [KafkaServer id=1] Retrying controlled shutdown after the previous attempt failed... (kafka.server.KafkaServer)[2023-04-10 14:18:16,049] WARN [KafkaServer id=1] Retrying controlled shutdown after the previous attempt failed... (kafka.server.KafkaServer)[2023-04-10 14:18:21,081] WARN [KafkaServer id=1] Retrying controlled shutdown after the previous attempt failed... (kafka.server.KafkaServer)[2023-04-10 14:18:21,084] WARN [KafkaServer id=1] Proceeding to do an unclean shutdown as all the controlled shutdown attempts failed (kafka.server.KafkaServer)[2023-04-10 14:18:27,279] INFO [KafkaServer id=1] shut down completed (kafka.server.KafkaServer)