QuorumPeerMain和ZooKeeperServerMain
我们在源码中可以找到这两个类,主要区别是一个是集群模式一个是独立模式。我们在后台启动并使用jps -l的时候会发现
kafka对应的进程主类是: org.apache.zookeeper.server.quorum.QuorumPeerMain
所以我们从QuorumPeerMain开始看
启动
直接看源码
1 | public static void main(String[] args) { |
从上面的代码中可以看到启动的主要步骤有三个:
- 加载配置QuorumPeerConfig
- 启动DatadirCleanupManager线程
- 根据配置来判断是启动集群环境和单机环境。
加载配置我们略过,主要是从文件中读取properties,我们重点看后面两个,因为我们环境中主要是集群环境
DatadirCleanupManager启动过程
这个类通过使用指定的’autopurge.purgeInterval’来调度自动清除任务,从而管理快照和相应事务日志的清理。—官方说明
这个怎么理解呢?
因为Zookeeper的修改操作(增删改)都会记录一个日志,另外Zookeeper每隔一段时间会生成一次快照,这些会持续化到硬盘的文件中,
所以当运行一段时间后,文件数量和快照会非常多,而我们这个类主要任务就是定时清理这些文件。我们接着看源码。
类结构
1 | private PurgeTaskStatus purgeTaskStatus = PurgeTaskStatus.NOT_STARTED; // 状态: 未启动、已启动、完成三个状态 |
清理过程
主要是创建一个TimeTask的任务,复写run 方法
1 |
|
这里说一下Zookeeper的文件结构,两个重要的文件夹,一个是dataDir 一个是dataLogDir(如果没有配置的话,默认是dataDir),分别是快照(也就是整个内存中的树形节点数据)和事物日志。
所以上面的的过滤器,会匹配对应的前缀log.和snapshot.
手动清理 ./zkCleanup.sh 其实主要原理就是调用这个类 org.apache.zookeeper.server.PurgeTxnLog “$ZOODATALOGDIR” “$ZOODATADIR” $*
单机启动过程
参考Zookeeper单机模式启动
单机启动过程中main函数与QuorumPeerMain一样,都是调用initializeAndRun–>初始化配置ServerConfig(内部使用QuorumPeerConfig,再复制属性)再启动
看主要启动逻辑runFromConfig:
1 | LOG.info("Starting server"); |
步骤解析:
- 启动度量程序,使用反射的方式根据配置中的类名创建一个实例,监控指标,默认是DefaultMetricsProvider
- 创建结束钩子
- 创建一个AdminServer 用来管理ZooKeeperServer。AdminServer是3.5.0版本中新增特性,是一个内置的Jettry服务,它提供了一个HTTP接口为四字母单词命令。默认的,服务被启动在8080端口,并且命令被发起通过URL “/commands/[command name]”,例如,http://localhost:8080/commands/stat
- 配置连接的服务框架ServerCnxnFactory并启动,这是核心服务,之前是NIO实现的,后面的版本增加Netty框架实现,后面继续分析其启动过程
- 配置安全相关
- 配置定时清除容器节点和临时节点
- 等待结束
集群启动过程
集群模式的入口是 runFromConfig(config); 其实原理和单机模式类似,前面也是执行一些度量监控子进程,我们来看核心代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public synchronized void start() {
if (!getView().containsKey(myid)) {
throw new RuntimeException("My id " + myid + " not in the peer list");
}
loadDataBase(); // 加载数据
startServerCnxnFactory(); // 启动网络服务
try {
adminServer.start();
} catch (AdminServerException e) {
LOG.warn("Problem starting AdminServer", e);
System.out.println(e);
}
startLeaderElection();
startJvmPauseMonitor();
super.start();
} - 加载数据,也就是持久化在文件里面的数据
- 启动io服务
- 启动AdminServer
- 进行主从选举
- 启动一个简单的线程,健康程序是否异常
这个几个过程和独立模式有点类似,主要不同的地方就是,多了主从选举,后续我们队各个过程惊醒梳理