ZooKeeper啟動過程 1.如何啟動
zkServer.sh【Linux】或 zkServer.cmd【Windows】
以zkServer.cmd為例(zkServer.sh中內容太多):
可以清晰的看出:調用了QuorumPeerMain這個類,傳的參數為%ZOOCFG%【在zkEnv.cmd中定義,就是zoo.cfg】。
到QuorumPeerMain類中一看,果然有個main方法,且接受一個參數【設定檔路徑】:
當然,接受的參數不是一個也沒關係,只不過就不能叢集了,只能以單機模式運行。僅當接受一個參數作為設定檔路徑,且此設定檔沒有設定為單機模式,才會開啟ZooKeeper叢集啟動過程【上圖120行,runFromConfig】。
2.啟動過程源碼分析
runFromConfig:
可以看出,程式轉移到了QuorumPeer,首先設定一系列zoo.cfg中的屬性值,而後start,QuorumPeer繼承了Thread類,自然轉到了QuorumPeer.run()。
run方法太長了,精簡了一下,只留了骨架:
@Override public void run() { /// JMX... try { /* * Main loop */ while (running) { switch (getPeerState()) { case LOOKING: /// ... setCurrentVote(makeLEStrategy().lookForLeader()); /// ... break; case OBSERVING: try { setObserver(makeObserver(logFactory)); observer.observeLeader(); } catch (Exception e) { } finally { observer.shutdown(); setObserver(null); updateServerState(); } break; case FOLLOWING: try { setFollower(makeFollower(logFactory)); follower.followLeader(); } catch (Exception e) { } finally { follower.shutdown(); setFollower(null); updateServerState(); } break; case LEADING: try { setLeader(makeLeader(logFactory)); leader.lead(); setLeader(null); } catch (Exception e) { } finally { if (leader != null) { leader.shutdown("Forcing shutdown"); setLeader(null); } updateServerState(); } break; } } } finally { /// clear JMX } }
可以看出,只要沒有stop或者沒有異常拋出,這個線程便一直在運行,沒有後續更多的操作了,全部在這個迴圈裡。
到此為止,ZooKeeper叢集中的這一個節點【Peer】啟動完畢。
從run()方法可以清晰的看到,ZooKeeper中的節點可以有四種狀態:
LOOKING OBSERVING FOLLOWING LEADING
其中,getPeerState()方法中state初始化為LOOKING,因此每一個節點啟動時的狀態都是LOOKING。
下一步,就是參與投票,選出ZooKeeper叢集的Leader,見下篇文章:ZooKeeper FastLeaderElection演算法。