# zookeeper 单机版server启动

单机版zookeeper的启动类为org.apache.zookeeper.server.ZooKeeperMain.java

1 启动参数

ZooKeeper启动参数有两种配置方式:

方式1:main方法中传入四个参数,其中前两参数必填,后两个参数可选。分别为:对客户端暴露的端口clientPortAddress, 存放事务记录、内存树快照记录的dataDir, 用于指定seesion检查时间间隔的tickTime, 控制最大客户端连接数的maxClientCnxns。

方式2:给出启动参数配置文件路径,当args启动参数只有一个时,ZooKeeperServerMain 中main方法,会认为传入了配置文件路径,默认情况下该参数是传conf目录中的zoo.cfg。

    protected void initializeAndRun(String[] args)
        throws ConfigException, IOException, AdminServerException
    {
        try {
            ManagedUtil.registerLog4jMBeans();
        } catch (JMException e) {
            LOG.warn("Unable to register log4j JMX control", e);
        }
        ServerConfig config = new ServerConfig();
        if (args.length == 1) {
            config.parse(args[0]);///对应方式2,传入配置文件地址
        } else {
            config.parse(args);///对应方式1,传入启动参数
        }
        runFromConfig(config);
    }

2 启动流程

ZooKeeperServerMain中,真正实现启动逻辑的是runFromConfig方法。
启动流程:

1:初始化一个事物、内存树快照记录器对象。

2:初始化一个单机版ZooKeeperServer对象,主要功能是创建处理客户端传来的request的处理链,当然也包括记录其他一些配置,ZKDatabase、maxSessionTimeout等。

3:初始化一个CountDownLatch对象shutDownLatch,用于线程之间协作,其主要有两个方法,countDown(), await(),countDowan() 方法使计数减一。调用await()方法会一直阻塞,直到计数变为0。在这里shutDownLatch负责在发生错误时关闭zookeeper服务。

4:初始化自带的管理后台server,默认容器是jetty。可以在配置文件中,配置

zookeeper.admin.enableServer = false

让zookeeper不会启动管理后台服务。

5:创建负责真正和客户端连接的ServerCnxnFactory对象cnxnFactory,在这里,可以通过配置选择使用JAVA自带的异步IO负责连接,也可以通过配置zookeeper.serverCnxnFactory,选择使用netty作为连接服务端,创建后,会将第2步的ZooKeeperServer对象,作为参数传递到cnxnFactory,然后启动服务。

6:根据配置决定是否初始化负责安全连接的secureCnxnFactory。

7:初始化ContainerManager对象,负责管理container ZNodes。

代码如下:

public void runFromConfig(ServerConfig config) throws IOException, AdminServerException {
        LOG.info("Starting server");
        FileTxnSnapLog txnLog = null;
        try {
            // 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);
            final ZooKeeperServer zkServer = new ZooKeeperServer(txnLog,
                    config.tickTime, config.minSessionTimeout, config.maxSessionTimeout, null);

            // 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));

            // Start Admin server
            adminServer = AdminServerFactory.createAdminServer();
            adminServer.setZooKeeperServer(zkServer);
            adminServer.start();

            boolean needStartZKServer = true;
            if (config.getClientPortAddress() != null) {
                cnxnFactory = ServerCnxnFactory.createFactory();
                cnxnFactory.configure(config.getClientPortAddress(), config.getMaxClientCnxns(), 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(), 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)
            );
            containerManager.start();

            // 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();

            if (cnxnFactory != null) {
                cnxnFactory.join();
            }
            if (secureCnxnFactory != null) {
                secureCnxnFactory.join();
            }
            if (zkServer.canShutdown()) {
                zkServer.shutdown();
            }
        } catch (InterruptedException e) {
            // warn, but generally this is ok
            LOG.warn("Server interrupted", e);
        } finally {
            if (txnLog != null) {
                txnLog.close();
            }
        }
    }

3 小结

单机版ZooKeeper,启动类是ZooKeeperServerMain。最终调用ZooKeeperServer的startup()方法来处理request。可以通过配置选择使用JAVA自带NIO或者netty作为异步连接服务端。

你可能感兴趣的:(zookeeper)