上一篇讲到了zookeeper的网络处理模型,下面是启动函数的全部内容,包含zkserver相关以及其他线程活动,这里不做重点分析对象。
/**
* Run from a ServerConfig.
* @param config ServerConfig to use.
* @throws IOException
* @throws AdminServerException
*/
public void runFromConfig(ServerConfig config) throws IOException, AdminServerException {
LOG.info("Starting server");
FileTxnSnapLog txnLog = null;
try {
try {
metricsProvider = MetricsProviderBootstrap.startMetricsProvider( //指标记录类
config.getMetricsProviderClassName(),
config.getMetricsProviderConfiguration());
} catch (MetricsProviderLifeCycleException error) {
throw new IOException("Cannot boot MetricsProvider " + config.getMetricsProviderClassName(), error);
}
ServerMetrics.metricsProviderInitialized(metricsProvider);
// Note that this thread isn't going to be doing anything else,
// so rather than spawning another thread, we will just call
// run() in this thread.
// create a file logger url from the command line args
txnLog = new FileTxnSnapLog(config.dataLogDir, config.dataDir); //创建数据和日志文件类
JvmPauseMonitor jvmPauseMonitor = null;
if (config.jvmPauseMonitorToRun) {
jvmPauseMonitor = new JvmPauseMonitor(config); //jvm暂停进程监控,默认不开启
}
//初始化配置,为zkserver相关线程做相关准备
final ZooKeeperServer zkServer = new ZooKeeperServer(jvmPauseMonitor, txnLog, config.tickTime, config.minSessionTimeout, config.maxSessionTimeout, config.listenBacklog, null, config.initialConfig);
txnLog.setServerStats(zkServer.serverStats()); //重复设置了一遍
// Registers shutdown handler which will be used to know the
// server error or shutdown state changes.
final CountDownLatch shutdownLatch = new CountDownLatch(1);
zkServer.registerServerShutdownHandler(new ZooKeeperServerShutdownHandler(shutdownLatch)); //当server发生故障,利用CountDownLatch停止主线程阻塞,结束进程
// Start Admin server
adminServer = AdminServerFactory.createAdminServer();
adminServer.setZooKeeperServer(zkServer);
adminServer.start(); //使用adminserver 来获取zookeeper相关指标和信息,封装了命令类,来从zkserver实例(前面zkserver中基本将所有配置类存储到zkserver中)中获取相关信息,集群默认不会开启的
boolean needStartZKServer = true;
if (config.getClientPortAddress() != null) {
cnxnFactory = ServerCnxnFactory.createFactory(); //server连接线程初始化工厂,初始化的是NIOServerCnxnFactory,还是一个netty的工厂类
cnxnFactory.configure(config.getClientPortAddress(), config.getMaxClientCnxns(), config.getClientPortListenBacklog(), false);
cnxnFactory.startup(zkServer); //启动相关进程
// zkServer has been started. So we don't need to start it again in secureCnxnFactory.
needStartZKServer = false;
}
if (config.getSecureClientPortAddress() != null) {
secureCnxnFactory = ServerCnxnFactory.createFactory();
secureCnxnFactory.configure(config.getSecureClientPortAddress(), config.getMaxClientCnxns(), config.getClientPortListenBacklog(), true);
secureCnxnFactory.startup(zkServer, needStartZKServer);
}
containerManager = new ContainerManager(
zkServer.getZKDatabase(),
zkServer.firstProcessor,
Integer.getInteger("znode.container.checkIntervalMs", (int) TimeUnit.MINUTES.toMillis(1)),
Integer.getInteger("znode.container.maxPerMinute", 10000),
Long.getLong("znode.container.maxNeverUsedIntervalMs", 0)
);
containerManager.start(); //定时删除checks container nodes that have a cversion > 0 and have no children.
ZKAuditProvider.addZKStartStopAuditLog();
// Watch status of ZooKeeper server. It will do a graceful shutdown
// if the server is not running or hits an internal error.
shutdownLatch.await();
shutdown(); //关闭cnxnFactory等线程
if (cnxnFactory != null) {
cnxnFactory.join(); //等待cnxnFactory内线程关闭
}
if (secureCnxnFactory != null) {
secureCnxnFactory.join();
}
if (zkServer.canShutdown()) {
zkServer.shutdown(true); //关闭zkserver相关进程
}
} catch (InterruptedException e) {
// warn, but generally this is ok
LOG.warn("Server interrupted", e);
} finally {
if (txnLog != null) {
txnLog.close(); //关闭文件类
}
if (metricsProvider != null) {
try {
metricsProvider.stop(); //关闭指标计算
} catch (Throwable error) {
LOG.warn("Error while stopping metrics", error);
}
}
}
}
主要看下zkserver启动的相关线程,后续请求分析可能会分析到,这里变量意义和线程作用暂时也无法明确,后续会分析到。
private void startupWithServerState(State state) {
if (sessionTracker == null) {
createSessionTracker(); //传入ticktime的sessiontracker的超时阈值
}
startSessionTracker(); //开始检测session超时
setupRequestProcessors(); //请求前置处理器,是一个生产消费队列,对每个请求状态码进行判断,分别进行请求前置处理
startRequestThrottler();
registerJMX(); //注册jmx bean
startJvmPauseMonitor(); //jvm停止监控,默认不开启
registerMetrics(); //通过zxdb和zkserver填写相关指标
setState(state);
requestPathMetricsCollector.start(); //请求路径指标收集
localSessionEnabled = sessionTracker.isLocalSessionsEnabled();
notifyAll();
}
上述zkserver分析完后,整个zkserver的启动流程就差不多,下面开始搞客户端启动,并且连接单机zkserver过程。