bigywater.tech
ZooKeeper · 14

会话风暴

成百上千个客户端同时断开又同时重连,就是「会话风暴」。这篇用 300 个 kazoo 客户端,量建立会话的代价、服务端重启后全部重连的时间分布,以及会话超时较短时有多少会话被判定过期。

zxid +300
300 个新会话 = 300 个 createSession 写事务
1161 ms / 11.5 s
服务端重启后客户端重连时间的中位数 / 最慢
59 / 300
会话超时 4 s、服务端停 6 s 后状态出现过 LOST 的客户端数

建立会话的代价

实测 · 本机执行输出
  300 个会话建立用时 166 ms(1812 个/秒);zxid 增加了 300(= 会话数);服务端连接数 zk_num_alive_connections = 301

服务端重启后的重连

实测 · 本机执行输出
  服务端重启后能响应用时 642 ms;300/300 个客户端重新 CONNECTED:第一个 482 ms、中位 1161 ms、最后一个 11517 ms(相对服务端开始启动)
  会话保持不变(会话 id 集合相同): True | 重启后 zk_global_sessions / alive connections = 300 / 301

300 个客户端对一个单机 ZooKeeper 来说负载并不大;如果是几千个客户端,客户端自己的重连退避与服务端的连接限流(第 19、26 篇)会变得更重要,本文没有测到那个规模。

会话超时较短时

实测 · 本机执行输出
  重启后 288/300 个客户端已连上,其中状态出现过 LOST(会话过期)的 59 个,换了新会话 id 的 71 个;重启后 zxid 增加 130(新会话 + 过期会话的 closeSession 事务)

数字每次运行都会不同(取决于恢复时机)。它说明的是:会话超时设得太短,一次几秒的重启就可能让一批会话过期,临时节点(比如服务注册)集中消失,引发二次风暴。

分步演示

会话风暴
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / ZooKeeper 3.9.6(brew 安装的 jar,用 java -cp 直接启动自己的实例,OpenJDK 17 Temurin,JVM 堆 128 MiB)/ 本机回环端口 7300+,数据在临时目录;默认 tickTime=2000;计时用 time.perf_counter,数字每次运行会有小幅抖动。单机,JVM 堆 256 MiB,maxClientCnxns=1000;300 个 kazoo 客户端(同一进程内的线程);各场景只测一次
    • 没有验证:几千个以上的客户端、Java 客户端的重连退避、集群里 leader 重启的风暴、服务端连接限流(connection throttling)的效果、重连时间尾部的真正原因
    京ICP备2026067502号-1京公网安备11010502063487号