前言
今年五一认真整理以前凌凌散散的学习内容,发现虽然看得多,但是如果不去看看源码,真的是不深刻,没什么感觉,这也是为什么要重新整理ZooKeeper的相关学习笔记了,在前面的时候我们介绍ZooKeeper的一些重要的概念,在整体上对ZooKeeper 有了一个简单的认识,下面我们再从服务端的启动流程来了解了解,本小节不会将集群的选举过程,这个将放在下一篇文章中介绍,本节知识整体了解一下服务端的启动运作流程。
ZooKeeper 系列文章 会讲一些重要的功能和概念,主要包括:
- 重要概念介绍 - 整体视图的认识
- 服务端启动流程
- 集群选举过程
- 会话管理
- 读写请求操作
- 数据与存储
本节主要 讲一下 服务端启动流程,对于前面内容可以点击相关链接进行跳转。
概览
以 3.6.1
版本作为分析。主要从服务端,结合部分源码,来了解 ZooKeeper的启动流程。
ZooKeeper 服务的启动方式分为三种,即单机模式、伪分布式模式、分布式模式。本章节主要研究分布式模式的启动模型,其主要要经过 Leader 选举,集群数据同步,启动服务器(走马观花的看)。
分布式模式下的启动过程主要包括如下阶段,
- 解析 config 文件;
- 本地文件数据恢复;
- Leader选举;
- 其它服务器和Leader数据同步;
- 初始化 ZooKeeperServer 进入各自角色服务;
整体架构
首先 我们先来看看ZooKeeperServer服务端的整体架构,如下图所示:
看不懂也没关系,先了解一下大概的内容,后面会细说里面的东西,下面简单介绍一下里面的名词和功能
» ZooKeeper Client : 代表的客户端,本次我们主要看服务端,因此客户端的东西就省略了.
» ServerCnxnFactory : ZooKeeper中使用ServerCnxnFactory管理与客户端的连接,其有两个实现
一个是NIOServerCnxnFactory,使用Java原生NIO实现;
一个是NettyServerCnxnFactory,使用netty实现;使用ServerCnxn代表一个客户端与服务端的连接.
» Session Tracker: 服务端对会话管理器,负责会话的创建,管理和清理等工作.
» RequestProcessor: ZooKeeper的请求处理链(责任链模式).
» LearnerCnxAcceptor: 用于负责接收所有非Leader服务器的连接请求
用 Learner 指代 除Leader 服务器以外的其余的服务器
» LearnerHandler: 负责Leader 和 某个Learner服务器之间的消息通信和数据同步
Leader 接收到来自其他机器的连接创建请求后,会创建一个 LearnerHandler实例,每个LearnerHandler实例都对应了一个Leader 和Learner服务器之间的连接
» ZKDatabase : 内存数据库,负责管理ZooKeeper的所有会话,数据存储和事务日志.
ZKDatabase 会定时向磁盘dump快照数据,同时在ZooKeeper服务器启动的时候,会通过磁盘的事务日志和快照数据文件恢复成一个完整的内存数据库.
» FileTxnSnapLog:事务日志和快照数据访问层,用于衔接上层业务和底层数据存储
底层数据包含了事务日志和快照数据两部分,因此 FileTxnSnapLog 内部又分为FileTxnLog和FileSnap,分别负责事务日志管理器和快照数据管理器
» Leader Election:封装了 Leader 选举算法的逻辑.
集群模式启动
流程图
入口在 QuorumPeerMain#main
配置文件解析
QuorumPeerConfig config = new QuorumPeerConfig();
if (args.length == 1) {
config.parse(args[0]);
}
解析配置文件zoo.cfg ,该文件配置了ZooKeeper 运行时的基本参数,包括 tickTime,dataDir和clientPort等参数信息,这里就不多讲了。
历史文件清理器
// Start and schedule the the purge task
DatadirCleanupManager purgeMgr = new DatadirCleanupManager(
config.getDataDir(),
config.getDataLogDir(),
config.getSnapRetainCount(),
config.getPurgeInterval());
purgeMgr.start();
从3.4.0 版本开始,ZooKeeper 增加了自动清理历史数据文件的机制,包括对事物日志和快照数据文件进行定时清理。
初始化 QuorumPeer
QuorumPeer 是集群模式下特有的对象,ZooKeeper实例的托管者,从集群层面看,代表了ZooKeeper集群中的一台机器,在运行期间,QuorumPeer 会不断的检测当前服务器实例的运行状态,同时根据情况发起Leader选举。
QuorumPeer 是 Thread 的子类
下面贴了部分代码,删减了部分,方便后面对照看,建议读者对照源码阅读
// 管理与客户端的连接
ServerCnxnFactory cnxnFactory = null;
ServerCnxnFactory secureCnxnFactory = null;
if (config.getClientPortAddress() != null) {
cnxnFactory = ServerCnxnFactory.createFactory();
cnxnFactory.configure(config.getClientPortAddress(), config.getMaxClientCnxns(), config.getClientPortListenBacklog(), false);
}
quorumPeer = getQuorumPeer();
/**
* 创建 ZooKeeper 数据管理器 FileTxnSnapLog
* FileTxnSnapLog 是ZooKeeper上层服务器和底层数据存储之间的对接层
* 提供了一列操作数据文件的接口,包括事务日志文件和快照数据文件
* ZooKeeper根据zoo.cfg 文件解析出来的快照数据目录 dataDir
* 和事务日志目录dataLogDir 来创建FileTxnSnapLog
*/
quorumPeer.setTxnFactory(new FileTxnSnapLog(config.getDataLogDir(), config.getDataDir()));
quorumPeer.enableLocalSessions(config.areLocalSessionsEnabled());
quorumPeer.enableLocalSessionsUpgrading(config.isLocalSessionsUpgradingEnabled());
quorumPeer.setElectionType(config.getElectionAlg());
// 设置 myId(serverId)
quorumPeer.setMyid(config.getServerId());
quorumPeer.setTickTime(config.getTickTime());
quorumPeer.setMinSessionTimeout(config.getMinSessionTimeout());
quorumPeer.setMaxSessionTimeout(config.getMaxSessionTimeout());
quorumPeer.setInitLimit(config.getInitLimit());
quorumPeer.setSyncL