文章目录
- Zookeeper 服务器启动过程
- zookeeper服务端整体架构图
- 单机版服务器启动过程
- 预启动
- 初始化
- 集群服务器启动过程
- 预启动
- 初始化
- Leader 选举
- Leader 和 Follower 启动期交互过程
- Leader 和 Follower 启动
Zookeeper 服务器启动过程
zookeeper服务端整体架构图
zookeeper 服务器的启动,大致可以分为以下五个步骤:
- 配置文件解析
- 初始化数据管理器
- 初始化网络I/O管理器
- 数据恢复
- 对外服务
单机版服务器启动过程
上图的过程可以分为预启动和初始化过程:
预启动
- 统一由 QuorumPeerMain 作为启动类。无论单机或集群,在 zkServer.cmd 和 zkServer.sh 中都配置了 QuorumPeerMain 作为启动入口类。
- 解析配置文件 zoo.cfg。zoo.cfg 配置运行时的基本参数,如 tickTime、dataDir、clientPort 等参数。
- 创建并启动历史文件清理器 DatadirCleanupManager 。对事务日志和快照数据文件进行定时清理。
- 判断当前是集群模式还是单机模式启动。若是单机模式,则委托给 ZookeeperServerMain 进行启动。
- 再次进行配置文件zoo.cfg的解析。
- 创建服务器实例 ZookeeperServer。Zookeeper 服务器首先会进行服务器实例的创建,然后对该服务器实例进行初始化,包括连接器、内存数据库、请求处理器等组件的初始化。
初始化
- 创建服务器统计器 ServerStats。ServerStats 是 Zookeeper 服务器运行时的统计器。
- 创建 Zookeeper 数据管理器 FileTxnSnapLog。FileTxnSnapLog 是 zookeeper 上层服务器和底层数据之间的对接层,提供了一系列操作数据文件的接口,如事务文件和快照数据文件。Zookeeper 根据 zoo.cfg 文件解析出来的快照数据目录 dataDir 和事务日志目录 dataLogDir 来创建 FileTxnSnapLog。
- 设置服务器 tickTime 和会话超时时间限制。
- 创建 ServerCnxnFactory 。通过配置系统属性 zookeeper.serverCnxnFactory 来指定使用 zookeeper 自己实现的 NIO 还是使用 Netty 框架作为 zookeeper服务端网络连接工厂。
- 初始化 ServerCnxnFactory。zookeeper会初始化 Thread 作为 ServerCnxnFactory 的主线程,然后再初始化 NIO 服务器。
- 启动 ServerCnxnFactory 主线程,进入Thread 的 run 方法,此时服务器还不能处理客户端请求。
- 恢复本地数据。启动时,需要从本地快照数据文件和事务日志进行数据恢复。
- 创建并启动会话管理器。zookeeper 会创建会话管理器 SessionTracker 进行会话管理。
- 初始化 zookeeper 的请求处理链。zookeeper 处理请求方式为责任链模式的实现,会有多个请求处理器依次处理一个客户端请求,在服务器启动时,会将这些请求处理器串联成一个请求处理链。
- 注册 JMX 服务。zookeeper 会将服务器运行时的一些信息以 JMX 的方式暴露给外部。
- 注册 zookeeper 服务实例。将 zookeeper 服务器实例注册给 ServerCnxnFactory ,之后 zookeeper就可以对外提供服务 。
集群服务器启动过程
单机和集群服务器的启动在很多地方是一致的,其流程图如下:
上图的过程可以分为预启动、初始化、Leader 选举、Leader和Follower启动期交互、Leader与Follower启动 等过程。
预启动
- 统⼀由QuorumPeerMain作为启动类。
- 解析配置⽂件zoo.cfg。
- 创建并启动历史文件清理器 DatadirCleanupFactory。
- 判断当前是集群模式还是单机模式的启动。在集群模式中,在zoo.cfg⽂件中配置了多个服务器地址,可以选择集群启动。
初始化
- 创建ServerCnxnFactory。
- 初始化ServerCnxnFactory。
- 创建Zookeeper数据管理器FileTxnSnapLog。
- 创建QuorumPeer实例。Quorum是集群模式下特有的对象,是Zookeeper服务器实例(ZooKeeperServer)的托管者,QuorumPeer代表了集群中的⼀台机器,在运行期间, QuorumPeer会不断检测当前服务器实例的运行状态,同时根据情况发起Leader选举。
- 创建内存数据库ZKDatabase。ZKDatabase负责管理ZooKeeper的所有会话记录以及 DataTree和事务日志的存储。
- 初始化QuorumPeer。将核心组件如FileTxnSnapLog、ServerCnxnFactory、ZKDatabase 注册到QuorumPeer中,同时配置QuorumPeer的参数,如服务器列表地址、Leader选举算法和会话超时时间限制等。
- 恢复本地数据。
- 启动ServerCnxnFactory主线程。
Leader 选举
- 初始化 Leader 选举。
集群模式特有,zookeeper 首先会根据自身的服务器 ID (SID)、最新的事务ID(ZXID)和当前服务器epoch(currentEpoch)来生成一个初始化投票,在初始化过程中,每个服务器都会给自己投票。然后根据zoo.cfg 的配置,创建指定的 Leader 选举算法实现,zookeeper 提供了三种算法(LeaderElection、AuthFastLeaderElection、FastLeaderElection),可以通过 zoo.cfg 中的 electionAlg 属性来指定,但目前只支持 FastLeaderElection 选举算法。
在初始化阶段,zookeeper 会创建 Leader 选举所需的网络 I/O 层 QuorunCnxManager,同时启动对 Leader 选举端口的监听,等待集群中其他服务器创建连接。 - 注册 JMX 服务。
- 检测当前服务器状态
运行期间,QuorumPeer 会不断检测当前服务器状态。在正常情况下,zookeeper 服务器的状态在 LOOKING/LEADING/FOLLOWING/OBSERVING 之间进行切换。在启动阶段,QuorumPeer 的初始状态是 LOOKING,因此开始进行 Leader 选举。 - Leader 选举
zookeeper 的选举过程,简单地讲,就是一个集群中所有的机器互相之间进行一系列投票,选举产生最合适的机器成为 Leader ,同时其余机器成为 Follower 或是 Observer 的集群机器角色初始化过程。
关于Leader 选举算法,简而言之,就是集群汇总哪个机器处理的数据越新(通常根据每个服务器处理过的最大 ZXID 来比较确定),越有可能成为 Leader ,其余机器称为 Follower 和 Observer。
Leader 和 Follower 启动期交互过程
到这里为止,zookeeper 已经完成了 Leader 选举,并且集群中每个服务器都已经确定了自己的角色。下面我们来对 Leader 和 Follower 在启动期间的交互进行介绍,其大致交互流程如图所示:
- 创建 Leader 服务器和 Follower 服务器
完成 Leader 选举后,每个服务器会根据自己服务器的角色创建相应的服务器实例,并进入各自角色的主流程 - Leader 服务器启动Follower接收器 LearnerCnxAcceptor
运行期间,leader 服务器需要和所有的服务器(统称为 Leader)保持连接以确认集群机器的存活情况,LearnCnxAcceptor 负责接收所有非 Leader 服务器的连接请求 - Learner 服务器开始和 Leader 建立连接
所有 Learner 会找到 Leader 服务器,并与其建立连接 - Leader 服务器创建 LearnerHandler
Leader 接收到来自其他机器的连接创建请求后,会创建一个 LearnHandler 实例,每个 LearnerHandler 实例都对应一个 Leader 与 Learner 服务器之间的连接,负责Leader和 Learner 之间几乎所有的消息通信和数据同步 - 向 Leader 注册
Learner 完成与 Leader 的连接后,会向 Leader 进行注册,即将 Learner 服务器的基本信息 (LearnerInfo),包括 SID 和 ZXID 发送给 Leader 服务器 - Leader 解析 Learner 信息,计算新的 epoch
Leader 接收到 Learner 服务器基本信息后,会解析出 Learner 的 SID 和 ZXID ,然后根据 ZXID 解析出对应的 epoch_of_learner ,并和当前的 Leader 服务器的 epoch_of_leader 进行比较,如果 Learner 的值比较大,则更新Leader 的 epoch_of_leader = epoch_of_learner + 1 。然后LearnHandler 进行等待,知道过半 Learner 已经向Leader 进行了注册,同时更新了 epoch_of_leader 后,Leader 就可以确定当前集群的 epoch了。 - 发送 Leader 状态
计算出新的 epoch 后,Leader 会将该选项以一个 LEADERINFO 消息形式发送给 Leader ,并等待 leader 的响应。 - Learner 发送ACK消息
Learner 接收到 LEADERINFO 后,会解析出 epoch 和 ZXID ,然后向 Leader 反馈一个 ACKEPOCH 响应。 - 数据同步
Leader 收到 Learner 的 ACKEPOCH 后,即可进行数据同步。 - 启动Leader和Learner服务器
当有过半 Learner 已经完成了数据同步,那么 Leader 和 Learner 服务器实例就可以启动了。
Leader 和 Follower 启动
- 创建启动会话管理器
- 初始化zookeeper请求处理链,集群模式的每个处理器也会在启动阶段串联请求处理链。
- 注册 JMX 服务。
至此,zookeeper集群启动完毕。