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,终止请求流程.