zookeeper 源码剖析

zookeeper 启动流程分析:

ZookeeperServerMain 作为入口类,在main函数里面先解析命令行参数,new ServerConfig(),然后执行runConfigFromServer()函数

实例化Zookeeper对象, 实例化Zookeeper对象的FileTxnSnapLog类成员变量,该对象有FileTxnLog和FileSnapLog两个类的成员变量,负责事务日志和内存数据dump工作.

创建NIOServerCnxnFactory对象,该对象实现了Runnable接口,有一个Thread类成员变量.调用NIOServerCnxnFactory对象的startup()方法:

    public void startup(ZooKeeperServer zks) throws IOException,
            InterruptedException {
        start();
        setZooKeeperServer(zks);
        zks.startdata();
        zks.startup();
    }
    public void start() {
        // ensure thread is started once and only once
        if (thread.getState() == Thread.State.NEW) {
            thread.start();  //会调用NIOServerCnxnFactory类的run()函数
        }
    }
run()函数伪代码如下:
   public void run() {
        while (!ss.socket().isClosed()) {
            try {
                selector.select(1000);  //方法阻塞1秒后返回
                Set selected = selector.selectedKeys();
                ArrayList selectedList = new ArrayList(
                        selected);
                Collections.shuffle(selectedList);
                for (SelectionKey k : selectedList) { //轮询所有已注册的selectionkey,看是否有可连接,可读或者可写事件发生
                    if ((k.readyOps() & SelectionKey.OP_ACCEPT) != 0) {  //有新连接进来
                        SocketChannel sc = ((ServerSocketChannel) k
                                .channel()).accept();
                        InetAddress ia = sc.socket().getInetAddress();
                        SelectionKey sk = sc.register(selector,SelectionKey.OP_READ);
                        NIOServerCnxn cnxn = createConnection(sc, sk);  //创建新的NIOServerCnxn对象,每一个该对象表示一个连接
                        sk.attach(cnxn);
                        addCnxn(cnxn);
                    } else if ((k.readyOps() & (SelectionKey.OP_READ | SelectionKey.OP_WRITE)) != 0) { //可读或可写事件发生
                        NIOServerCnxn c = (NIOServerCnxn) k.attachment();
                        c.doIO(k);
                    } else {
                        if (LOG.isDebugEnabled()) {
                            LOG.debug("Unexpected ops in select "
                                      + k.readyOps());
                        }
                    }
                }
                selected.clear();
            } catch (RuntimeException e) {
                LOG.warn("Ignoring unexpected runtime exception", e);
            } catch (Exception e) {
                LOG.warn("Ignoring exception", e);
            }
        }
        closeAll();
        LOG.info("NIOServerCnxn factory exited run method");
    }

再来看一下ZookeeperServer的startData()函数:

   public void startdata() throws IOException, InterruptedException {
        //check to see if zkDb is not null
        if (zkDb == null) {
            zkDb = new ZKDatabase(this.txnLogFactory);
        }  
        if (!zkDb.isInitialized()) {
            loadData();  //根据snaplog恢复内存数据DataTree
        }
    }
    
    public synchronized void startup() {
        if (sessionTracker == null) {
            createSessionTracker();
        }
        startSessionTracker();
        setupRequestProcessors();
        registerJMX();
        setState(State.RUNNING);
        notifyAll();
    }

分析setupRequestProcessors()函数:

   protected void setupRequestProcessors() {
        RequestProcessor finalProcessor = new FinalRequestProcessor(this);
        RequestProcessor syncProcessor = new SyncRequestProcessor(this,
                finalProcessor);  //第二个参数是下一个请求处理类RequestProcessor, 通过这样的方式实现了链式处理
        ((SyncRequestProcessor)syncProcessor).start();
        firstProcessor = new PrepRequestProcessor(this, syncProcessor);
        ((PrepRequestProcessor)firstProcessor).start();
    } 
从上面这段代码可以分析出,第一个请求处理类是PrepRequestProcessor,然后通过链式传递给下一个类FinalRequestProcessor,终止请求流程.



你可能感兴趣的:(zookeeper 源码剖析)