消费实例每分钟被踢一次,日志是 Member has left the group,同一时刻 GC 日志里有一次 12.4 秒的 Full GC,heartbeat 线程整段没发出请求。第一次遇到会往复杂处想,其实漏掉的多是个小前提。
# consumer.properties session.timeout.ms=30000 heartbeat.interval.ms=3000 java -Xlog:gc*:file=/tmp/gc.log:time,uptime -jar consumer.jar
心跳由独立线程发,但 Full GC 期间整个 JVM 停顿,心跳也跟着停。session.timeout.ms 只有 10000,超过就被协调者判定失联。这一点先确认清楚,后面就不用反复试。
「Kafka 会话超时」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。
改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。验证用真实数据走一遍,测试数据太干净,边界情况根本碰不到。
能分两步做的操作就别合成一步,中间看一眼返回值,出问题好判断。
具体做法是,先把 session.timeout.ms 调到 30000 给 GC 留余量;heartbeat.interval.ms 保持在三秒左右 不要跟着放大;同时压 Full GC 的停顿 换 G1 并限制最大暂停;确认踢出日志与 GC 时间点能对上。
改完照着核一遍,GC 日志里仍有停顿 但消费组不再出现成员离开的日志 lag 没有阶跃。
