集群事件日志里 Controller 在 10:05 到 11:05 之间切换了 9 次,每次伴随 20 到 40 秒的元数据不可用,客户端大量 LEADER_NOT_AVAILABLE。日志里能对上时间点,这种反而好排。

controller 与 zookeeper 的会话超时后触发重新选举。常见原因是 controller 所在 broker 的 Full GC 停顿超过 zookeeper.session.timeout.ms,也可能是机房网络抖动。这一点先确认清楚,后面就不用反复试。

grep -i 'session expired' /var/log/kafka/controller.log | tail -30
kafka-configs.sh --bootstrap-server kafka:9092 --describe \
  --entity-type brokers --entity-name 1

「Kafka Controller 切换」确认了原因之后,改动尽量只碰那一处,顺手改的东西后面最容易出问题。线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。

日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。权限不要一口气开到最大,先加到够用再往上试,范围小才好收。

把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。

处理上按这个顺序:先把 controller 所在 broker 的 GC 日志和切换时间点对齐;看 zookeeper 日志里 session expired 的具体时间;把 zookeeper.session.timeout.ms 从 6 秒调到 18 秒;给 controller 单独一台负载低的 broker 并限制堆大小。

结果对不对很好判断,连续三小时 controller 切换次数为 0 客户端不再出现 LEADER_NOT_AVAILABLE。

作者 9823189