JVM 的 GC 停顿是 ZooKeeper 运维里最常见的「莫名其妙」:请求突然变慢、会话莫名过期、follower 被踢出。这篇用真实的 Full GC 量一下停顿有多长、请求延迟怎么跟着变,再看 ZooKeeper 自带的停顿监视器靠不靠谱。
GC 日志里的 Full GC 停顿(ms):[14.065, 20.646, 35.14, 63.713, 82.943, 66.402, 59.89, 72.183, 64.26, 60.169];普通写延迟中位 1.72 ms,压测期间最大写延迟 99.2 ms GC 日志示例: [19.836s][info][gc] GC(82) Pause Full (Diagnostic Command) 124M->115M(285M) 60.169ms
这是为了观察而人为制造的:小堆 + 串行 GC + 手动触发 Full GC。生产环境用 G1 / ZGC 时停顿会短得多,但原理一样——停顿期间 ZooKeeper 的所有线程(包括处理请求和发心跳的)都停了。
日志里 JVM 停顿相关的行共 1 条,例:
Starting JVM Pause Monitor with infoThresholdMs:50 warnThresholdMs:200 and sleepTimeMs:500
mntr:zk_max_jvm_pause_time_ms = 10 | zk_avg_jvm_pause_time_ms = 5.0732 | zk_cnt_jvm_pause_time_ms = 41停顿超过 syncLimit × tickTime 时,leader 会把 follower 判定为掉线(第 46 篇);停顿超过会话超时的客户端会话过期(第 13 篇),临时节点消失。所以堆大小、GC 选择、会话超时和 syncLimit 要一起考虑。