1 單機版啟動
單機版啟動大致可以分為如下步驟:
- 配置文件解析
- 初始化數據管理器
- 初始化網絡IO管理器
- 數據恢復
- 對外服務

1.1 預啟動
在QuorumPeerMain作為啟動類,該類會進行如下操作:
- 解析
zoo.cfg配置文件 - 清理歷史數據
- 根據配置文件中服務器地址列表的數量,判斷是單機還是集群啟動
- 創建
ZooKeeperServerMain真正啟動ZK服務器
注意:QuorumPeerMain作為啟動類,是在zkServer.sh腳本中進行的配置。
1.2 初始化並啟動
ZooKeeperServerMain作為真正啟動單機版ZK服務器的核心實現,ZK服務器的啟動包括兩個方面:
- 網絡IO管理(ServerCnxnFactory):監聽2181端口,用於處理客戶端網絡請求處理
- 服務啟動(ZookeeperServer)
① 加載數據
② 應用會話管理
③ 創建請求處理鏈
④ 將ServerCnxnFactory注冊到ZookeeperServer中,以便ZookeeperServer可以利用ServerCnxnFactory獲取到客戶端請求。
Zookeeper使用鏈式方式處理客戶端請求,單機版啟動時,初始化的處理鏈如下:

2 集群版啟動

QuormPeer類是集群啟動過的核心實現:
- 啟動
ServerCnxnFactory接收客戶端請求 - 初始化Leader選舉算法
根據zoo.cfg文件中的electionArg屬性的值,創建相應的選舉算法,默認提供了3中算法:
- LeaderElection(已廢棄)
- AuthFastLeaderElection(已廢棄)
- FastLeaderElection:
- 啟動
QuormPeer線程選舉流程、執行Leader流程、Follower流程、Observer流程
2.1 初始化選舉算法
QuorumPeer中會首先獲取選舉算法,代碼如下:
// 代碼已經省略所有try{} catch{}部分
synchronized public void startLeaderElection() {
currentVote = new Vote(myid, getLastLoggedZxid(), getCurrentEpoch());
for (QuorumServer p : getView().values()) {
if (p.id == myid) {
myQuorumAddr = p.addr;
break;
}
}
if (myQuorumAddr == null) { /* 異常省略 */ }
if (electionType == 0) {
udpSocket = new DatagramSocket(myQuorumAddr.getPort());
responder = new ResponderThread();
responder.start();
}
this.electionAlg = createElectionAlgorithm(electionType);
}
protected Election createElectionAlgorithm(int electionAlgorithm){
Election le=null;
//此處使用工廠類更加適合
switch (electionAlgorithm) {
case 0:
le = new LeaderElection(this);
break;
case 1:
le = new AuthFastLeaderElection(this);
break;
case 2:
le = new AuthFastLeaderElection(this, true);
break;
case 3:
qcm = createCnxnManager();
QuorumCnxManager.Listener listener = qcm.listener;
if(listener != null){
listener.start();
le = new FastLeaderElection(this, qcm);
} else {
LOG.error("Null listener when initializing cnx manager");
}
break;
default:
assert false;
}
return le;
}
2.2 異步線程根據服務器角色進入相應流程
集群啟動會在QuormPeer的異步線程中循環判斷服務器的狀態,以便執行服務器相應的流程,簡易代碼如下:
while (running) {
switch (getPeerState()) {
case LOOKING:
setCurrentVote(makeLEStrategy().lookForLeader());
break;
case OBSERVING:
setObserver(makeObserver(logFactory));
observer.observeLeader();
break;
case FOLLOWING:
setFollower(makeFollower(logFactory));
follower.followLeader();
break;
case LEADING:
setLeader(makeLeader(logFactory));
leader.lead();
setLeader(null);
break;
}
}
}
3 選舉算法
待補充
