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<SelectionKey> selected = selector.selectedKeys();ArrayList<SelectionKey> selectedList = new ArrayList<SelectionKey>(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 nullif (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,终止请求流程.


猜你喜欢

转载自blog.51cto.com/14524696/2455527