bigywater.tech
ZooKeeper · 4

ZooKeeper 启动流程

ZooKeeper 启动时到底做了哪些事?与其读源码,不如把它的日志按时间戳排出来。这篇用同一个节点,看空数据目录首次启动、有数据重启、端口被占用三种情形的日志里程碑。

约 90 ms
空数据目录首次启动,日志里从读配置到容器清理线程启动的总时间
快照 + 日志
有数据时多一步「Reading snapshot / Snapshot loaded」
退出码 1
端口被占用时,JVM 记录 BindException 后退出

首次启动的日志里程碑

实测 · 本机执行输出
  +   0 ms  读配置文件                      Reading configuration from: <实验目录>
  +   4 ms  没有 server.N → 单机模式         Either no config or no quorum defined in config, running in standalone mode
  +   5 ms  ZooKeeperServerMain 启动     Starting server
  +  32 ms  创建服务实例(带会话超时范围)            Created server with tickTime 2000 ms minSessionTimeout 4000 ms maxSessionTimeout 40000 ms 
  +  41 ms  绑定客户端端口                    binding to port /127.0.0.1:7300
  +  50 ms  快照加载完成                     Snapshot loaded in 4 ms, highest zxid is 0x0, digest is 1371985504
  +  50 ms  启动时写一份新快照                  Snapshot taken in 1 ms
  +  58 ms  请求处理链第一环启动                 PrepRequestProcessor (sid:0) started, reconfigEnabled=false
  +  90 ms  容器节点清理线程启动                 Using checkIntervalMs=60000 maxPerMinute=10000 maxNeverUsedIntervalMs=0
  从启动进程到 srvr 能响应(含 JVM 启动、我的轮询间隔):425 ms

单机模式其实走的也是 QuorumPeerMain:它发现配置里没有 server.N,就转交给 ZooKeeperServerMain。(日志里「读配置」出现了两次,就是这次转交。)

有数据时的重启

实测 · 本机执行输出
  +   0 ms  读配置文件                      Reading configuration from: <实验目录>
  +   4 ms  没有 server.N → 单机模式         Either no config or no quorum defined in config, running in standalone mode
  +   5 ms  ZooKeeperServerMain 启动     Starting server
  +  34 ms  创建服务实例(带会话超时范围)            Created server with tickTime 2000 ms minSessionTimeout 4000 ms maxSessionTimeout 40000 ms 
  +  42 ms  绑定客户端端口                    binding to port /127.0.0.1:7300
  +  49 ms  读快照                        Reading snapshot <实验目录>
  +  83 ms  快照加载完成                     Snapshot loaded in 36 ms, highest zxid is 0x1772, digest is 12899551610955
  +  91 ms  启动时写一份新快照                  Snapshot taken in 7 ms
  + 100 ms  请求处理链第一环启动                 PrepRequestProcessor (sid:0) started, reconfigEnabled=false
  + 131 ms  容器节点清理线程启动                 Using checkIntervalMs=60000 maxPerMinute=10000 maxNeverUsedIntervalMs=0
  重启前最大 zxid 0x1772;重启到能响应:425 ms(第一次 425 ms)
  重启后 znode 数: 6005
  数据目录(version-2)里的文件: ['log.1', 'log.124c', 'log.15bf', 'log.32e', 'log.62f', 'log.875', 'log.b3c', 'log.e84', 'snapshot.0', 'snapshot.123f', 'snapshot.15a4', 'snapshot.1772', 'snapshot.2fe', 'snapshot.60d', 'snapshot.860', 'snapshot.b32', 'snapshot.e77']

文件名里的 zxid、事务日志与快照的关系在第 5 篇看。「启动到能响应」的耗时我没有放进结论:两次测出来是同一个数字,里面包含了 JVM 启动和我轮询的间隔,没有区分度。

端口被占用

实测 · 本机执行输出
  进程退出码: 1
  日志: ERROR o.a.z.s.ZooKeeperServerMain - Unexpected exception, exiting abnormally
  日志: java.net.BindException: Address already in use
  日志: ERROR o.a.z.u.ServiceUtils - Exiting JVM with code 1

分步演示

启动流程
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / ZooKeeper 3.9.6(brew 安装的 jar,用 java -cp 直接启动自己的实例,OpenJDK 17 Temurin,JVM 堆 128 MiB)/ 本机回环端口 7300+,数据在临时目录;默认 tickTime=2000;计时用 time.perf_counter,数字每次运行会有小幅抖动。日志取自自己配置的 logback 文件输出(INFO),只摘录与启动相关的行
    • 没有验证:集群模式的启动流程(选举、同步,见第 34、35、42 篇)、JVM 参数对启动时间的影响、数据量很大(GB 级)时的加载耗时(第 10 篇量了 20 万 znode)、zkServer.sh 脚本做了什么
    京ICP备2026067502号-1京公网安备11010502063487号