ZooKeeper服务端启动过程——单机模式

本文对单机模式下,ZooKeeper服务端的启动过程进行介绍

相关的类

  • QuorumPeerMain:服务端启动的入口类
  • DatadirCleanupManager:历史文件清理器
  • ZooKeeperServerMain:单机模式下的启动类

QuorumPeerMain类的main方法,如下:

public static void main(String[] args) {
        QuorumPeerMain main = new QuorumPeerMain();
        try {
            main.initializeAndRun(args);
        }catch(){
      //TODO
        }
}

在initializeAndRun(args)方法中进行一系列的初始化工作

protected void initializeAndRun(String[] args) throws ConfigException, IOException, AdminServerException
    {
        QuorumPeerConfig config = new QuorumPeerConfig();
        if (args.length == 1) {
            config.parse(args[0]);
        }
        // 定时,启动历史文件的清理器
        DatadirCleanupManager purgeMgr = new DatadirCleanupManager(config
                .getDataDir(), config.getDataLogDir(), config
                .getSnapRetainCount(), config.getPurgeInterval());
        purgeMgr.start();
    // 对启动方式进行判断,集群模式还是单机模式
        if (args.length == 1 && config.isDistributed()) {
        //集群模式的启动入口
            runFromConfig(config);
        } else {
        //单机模式的启动方式
            ZooKeeperServerMain.main(args);
        }
    }

至此,单机模式的启动方式完成了一下几个步骤:

  • 启动QuorumPeerMain类,执行main方法
  • 解析配置文件,加载配置参数
  • 启动定时的历史文件清理器DatadirCleanupManager
  • 启动ZooKeeperServerMain类,执行其main方法

到这一步,ZooKeeper服务端的启动任务已经转移到了ZooKeeperServerMain中,下面我们就看看在main方法中都进行了哪些操作。

 public static void main(String[] args) {
        ZooKeeperServerMain main = new ZooKeeperServerMain();
        try {
            main.initializeAndRun(args);
        }catch(){
        //TODO
        }
}

在initializeAndRun(args)完成的工作如下所示:

//注册log4j JMX mbeans
ManagedUtil.registerLog4jMBeans();
//从配置文件中启动服务端
runFromConfig(config);

在服务端的启动过程,涉及到的类有:

  • FileTxnSnapLog:这是ZooKeeper上层服务器和底层数据存储之间的一个对接层,提供了一系列操作数据文件的接口,这些数据文件包括事务日志文件和快照数据文件,入参为数据快照目录dataDir和事务日志目录dataLogDir
  • ServerStats:这是一个服务端的统计器,统计服务器运行的状态信息,关于这个类将在后面进行介绍
  • ZooKeeperServerShutdownHandler:当服务器shutdown之后的处理类,有一个CountDownLatch的同步器控制
  • ServerCnxnFactory
  • ZooKeeperServer
  • ContainerManager

ZooKeeperServerMain类中的runFromConfig(ServerConfig config)执行逻辑

主要代码如下:

public void runFromConfig(ServerConfig config) throws IOException, AdminServerException {
    //实例化一个ZooKeeper服务端的数据管理器,提供一些接口操作事务日志文件、快照数据文件
    FileTxnSnapLog txnLog = null; 
    //dataLogDir和dataDir是配置文件中的事务日志文件、数据快照文件的目录
    txnLog = new FileTxnSnapLog(config.dataLogDir, config.dataDir);
    //实例化一个ZooKeeperServer对象
    final ZooKeeperServer zkServer = new ZooKeeperServer(txnLog,config.tickTime, config.minSessionTimeout, config.maxSessionTimeout, null);
    //设置ServerStats
    txnLog.setServerStats(zkServer.serverStats());
    //向ZooKeeperServer对象注册一个ZooKeeperServerShutdownHandler
    final CountDownLatch shutdownLatch = new CountDownLatch(1);
    zkServer.registerServerShutdownHandler(new  ZooKeeperServerShutdownHandler(shutdownLatch));
    //得到一个ServerCnxnFactory对象,反射机制,具体看createFactory()方法
    cnxnFactory = ServerCnxnFactory.createFactory();
    //启动cnxnFactory, 在startup()中,进行主要的逻辑
    cnxnFactory.startup(zkServer);
}

cnxnFactory.startup(zkServer)是服务端启动的主要逻辑所在,该方法采用的是模板模式。代码如下:

public void startup(ZooKeeperServer zkServer) throws IOException, InterruptedException {
        startup(zkServer, true);
    }

其真正的处理逻辑是由startup(zkServer, true)负责完成的。实现类NIOServerCnxnFactory中的代码如下:

@Override
public void startup(ZooKeeperServer zks, boolean startServer)
            throws IOException, InterruptedException {
        //启动服务端的一些线程,后面在慢慢研究
        start(); 
        //设置ZooKeeperServer对应的ServerCnxnFactory
        setZooKeeperServer(zks);
        if (startServer) {
        //从FileTxnSnapLog中初始化数据
            zks.startdata();
            //启动ZooKeeperServer,完成诸如
            //创建并启动会话管理器SessionTracker
            //初始化ZooKeeper的请求处理链路
            //注册JMX服务
            //将ZooKeeperServer服务端的状态设置位running
            //通知所有阻塞在这里的线程
            zks.startup();
        }
 }

所以,在ZooKeeperServerMain这个类中,主要完成一系列初始化的配置+ServerCnxnFactory的runFromConfig。

具体的执行逻辑

  • 初始化一个ZooKeeper服务端的数据管理器FileTxnSnapLog,作为事务日志文件和快照数据文件的管理器
  • 解析配置参数,并根据FileTxnSnapLog对象来实例化一个ZooKeeperServer对象
  • 为ZooKeeperServer注册一个ZooKeeperServerShutdownHandler
  • 通过反射机制,得到一个ServerCnxnFactory对象
  • 调用ServerCnxnFactory对象的startup()方法。该方法的具体执行逻辑见上文中方法的代码。

ServerCnxnFactory对象的startup()方法的执行逻辑
主要完成线程的初始化,以及ZooKeeperServer对象的一些初始化工作,流程如下:

  • 调用ServerCnxnFactory的start方法,完成服务端网络连接的一些线程的问题(具体后文详细介绍,请持续关注)
  • ZooKeeper服务端的数据文件的恢复
  • 初始化并启动会话管理器,SessionTracker
  • 初始化ZooKeeper服务端的请求处理链,典型的责任链模式
    1. PrepRequestProcessor
    2. SyncRequestProcessor
    3. FinalRequestProcessor
  • 注册JMX服务
  • 设置状态为running,然后notifyAll

猜你喜欢

转载自blog.csdn.net/Shannon076/article/details/80988801