现象
消费端日志反复出现 Rebalance began 与 Revoking previously assigned partitions;每隔几分钟吞吐归零再恢复;日志里的 generation 不断增大;每次重平衡后部分消息被重复处理。
诊断
连续两次查看消费组状态,间隔约一分钟:
kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--describe --group orders --state --members --verbose
若 generation 持续变化、分区归属在没有发布的情况下漂移,或状态长期停在 PreparingRebalance,即可确认存在循环。随后在消费端日志中查原因:
kubectl logs deploy/orders-consumer --since=30m | \
grep -E 'Rebalance|max.poll.interval|poll timeout|LeaveGroup' | tail -50
出现 consumer poll timeout has expired 说明单批处理时间超过 max.poll.interval.ms;若是心跳失败,则要排查 GC 停顿、网络抖动或 session.timeout.ms 过小。最后用 --describe --under-replicated-partitions 和 broker 日志排除副本切换导致的成员抖动。
修复
降低 max.poll.records,让最慢一批也能在轮询间隔内处理完;确实单条耗时较长时,提高 max.poll.interval.ms 并把握手与处理线程分离。为消费者设置 group.instance.id 启用静态成员,滚动发布时不会触发全组重平衡;使用 CooperativeStickyAssignor 只撤销必须迁移的分区。示例配置:
max.poll.records=100
max.poll.interval.ms=600000
session.timeout.ms=60000
partition.assignment.strategy=org.apache.kafka.clients.consumer.CooperativeStickyAssignor
group.instance.id=orders-pod-3
验证
持续观察至少三个原本会触发重平衡的窗口:generation 应保持不变,状态稳定为 Stable,lag 单调下降,日志中不再出现 poll timeout。再用静态成员做一次 Pod 重启,确认成员能在会话超时内重新加入且不全量撤销分区。最后核对下游幂等指标,确保这次风暴没有留下重复副作用。