http://www.cnblogs.com/leesf456/p/6105276.html
一、前言
前面已經了解了Zookeeper會話相關知識點,接著來學習Zookeeper服務端相關細節。
二、服務端
服務端整體架構如下

Zookeeper服務器的啟動,大致可以分為以下五個步驟
1. 配置文件解析。
2. 初始化數據管理器。
3. 初始化網絡I/O管理器。
4. 數據恢復。
5. 對外服務。
2.1 單機版服務器啟動
單機版服務器的啟動其流程圖如下

上圖的過程可以分為預啟動和初始化過程。
1. 預啟動
1. 統一由QuorumPeerMain作為啟動類。無論單機或集群,在zkServer.cmd和zkServer.sh中都配置了QuorumPeerMain作為啟動入口類。
2. 解析配置文件zoo.cfg。zoo.cfg配置運行時的基本參數,如tickTime、dataDir、clientPort等參數。
3. 創建并啟動歷史文件清理器DatadirCleanupManager。對事務日志和快照數據文件進行定時清理。
4. 判斷當前是集群模式還是單機模式啟動。若是單機模式,則委托給ZooKeeperServerMain進行啟動。
5. 再次進行配置文件zoo.cfg的解析。
6. 創建服務器實例ZooKeeperServer。Zookeeper服務器首先會進行服務器實例的創建,然后對該服務器實例進行初始化,包括連接器、內存數據庫、請求處理器等組件的初始化。
2. 初始化
1. 創建服務器統計器ServerStats。ServerStats是Zookeeper服務器運行時的統計器。
2. 創建Zookeeper數據管理器FileTxnSnapLog。FileTxnSnapLog是Zookeeper上層服務器和底層數據存儲之間的對接層,提供了一系列操作數據文件的接口,如事務日志文件和快照數據文件。Zookeeper根據zoo.cfg文件中解析出的快照數據目錄dataDir和事務日志目錄dataLogDir來創建FileTxnSnapLog。
3. 設置服務器tickTime和會話超時時間限制。
4. 創建ServerCnxnFactory。通過配置系統屬性zookeper.serverCnxnFactory來指定使用Zookeeper自己實現的NIO還是使用Netty框架作為Zookeeper服務端網絡連接工廠。
5. 初始化ServerCnxnFactory。Zookeeper會初始化Thread作為ServerCnxnFactory的主線程,然后再初始化NIO服務器。
6. 啟動ServerCnxnFactory主線程。進入Thread的run方法,此時服務端還不能處理客戶端請求。
7. 恢復本地數據。啟動時,需要從本地快照數據文件和事務日志文件進行數據恢復。
8. 創建并啟動會話管理器。Zookeeper會創建會話管理器SessionTracker進行會話管理。
9. 初始化Zookeeper的請求處理鏈。Zookeeper請求處理方式為責任鏈模式的實現。會有多個請求處理器依次處理一個客戶端請求,在服務器啟動時,會將這些請求處理器串聯成一個請求處理鏈。
10. 注冊JMX服務。Zookeeper會將服務器運行時的一些信息以JMX的方式暴露給外部。
11. 注冊Zookeeper服務器實例。將Zookeeper服務器實例注冊給ServerCnxnFactory,之后Zookeeper就可以對外提供服務。
至此,單機版的Zookeeper服務器啟動完畢。
2.2 集群服務器啟動
單機和集群服務器的啟動在很多地方是一致的,其流程圖如下

上圖的過程可以分為預啟動、初始化、Leader選舉、Leader與Follower啟動期交互過程、Leader與Follower啟動等過程。
1. 預啟動
1. 統一由QuorumPeerMain作為啟動類。
2. 解析配置文件zoo.cfg。
3. 創建并啟動歷史文件清理器DatadirCleanupFactory。
4. 判斷當前是集群模式還是單機模式的啟動。在集群模式中,在zoo.cfg文件中配置了多個服務器地址,可以選擇集群啟動。
2. 初始化
1. 創建ServerCnxnFactory。
2. 初始化ServerCnxnFactory。
3. 創建Zookeeper數據管理器FileTxnSnapLog。
4. 創建QuorumPeer實例。Quorum是集群模式下特有的對象,是Zookeeper服務器實例(ZooKeeperServer)的托管者,QuorumPeer代表了集群中的一臺機器,在運行期間,QuorumPeer會不斷檢測當前服務器實例的運行狀態,同時根據情況發起Leader選舉。
5. 創建內存數據庫ZKDatabase。ZKDatabase負責管理ZooKeeper的所有會話記錄以及DataTree和事務日志的存儲。
6. 初始化QuorumPeer。將核心組件如FileTxnSnapLog、ServerCnxnFactory、ZKDatabase注冊到QuorumPeer中,同時配置QuorumPeer的參數,如服務器列表地址、Leader選舉算法和會話超時時間限制等。
7. 恢復本地數據。
8. 啟動ServerCnxnFactory主線程。
3. Leader選舉
1. 初始化Leader選舉。集群模式特有,Zookeeper首先會根據自身的服務器ID(SID)、最新的ZXID(lastLoggedZxid)和當前的服務器epoch(currentEpoch)來生成一個初始化投票,在初始化過程中,每個服務器都會給自己投票。然后,根據zoo.cfg的配置,創建相應Leader選舉算法實現,Zookeeper提供了三種默認算法(LeaderElection、AuthFastLeaderElection、FastLeaderElection),可通過zoo.cfg中的electionAlg屬性來指定,但現只支持FastLeaderElection選舉算法。在初始化階段,Zookeeper會創建Leader選舉所需的網絡I/O層QuorumCnxManager,同時啟動對Leader選舉端口的監聽,等待集群中其他服務器創建連接。
2. 注冊JMX服務。
3. 檢測當前服務器狀態。運行期間,QuorumPeer會不斷檢測當前服務器狀態。在正常情況下,Zookeeper服務器的狀態在LOOKING、LEADING、FOLLOWING/OBSERVING之間進行切換。在啟動階段,QuorumPeer的初始狀態是LOOKING,因此開始進行Leader選舉。
4. Leader選舉。通過投票確定Leader,其余機器稱為Follower和Observer。具體算法在后面會給出。
4. Leader和Follower啟動期交互過程
1. 創建Leader服務器和Follower服務器。完成Leader選舉后,每個服務器會根據自己服務器的角色創建相應的服務器實例,并進入各自角色的主流程。
2. Leader服務器啟動Follower接收器LearnerCnxAcceptor。運行期間,Leader服務器需要和所有其余的服務器(統稱為Learner)保持連接以確集群的機器存活情況,LearnerCnxAcceptor負責接收所有非Leader服務器的連接請求。
3. Leader服務器開始和Leader建立連接。所有Learner會找到Leader服務器,并與其建立連接。
4. Leader服務器創建LearnerHandler。Leader接收到來自其他機器連接創建請求后,會創建一個LearnerHandler實例,每個LearnerHandler實例都對應一個Leader與Learner服務器之間的連接,其負責Leader和Learner服務器之間幾乎所有的消息通信和數據同步。
5. 向Leader注冊。Learner完成和Leader的連接后,會向Leader進行注冊,即將Learner服務器的基本信息(LearnerInfo),包括SID和ZXID,發送給Leader服務器。
6. Leader解析Learner信息,計算新的epoch。Leader接收到Learner服務器基本信息后,會解析出該Learner的SID和ZXID,然后根據ZXID解析出對應的epoch_of_learner,并和當前Leader服務器的epoch_of_leader進行比較,如果該Learner的epoch_of_learner更大,則更新Leader的epoch_of_leader = epoch_of_learner + 1。然后LearnHandler進行等待,直到過半Learner已經向Leader進行了注冊,同時更新了epoch_of_leader后,Leader就可以確定當前集群的epoch了。
7. 發送Leader狀態。計算出新的epoch后,Leader會將該信息以一個LEADERINFO消息的形式發送給Learner,并等待Learner的響應。
8. Learner發送ACK消息。Learner接收到LEADERINFO后,會解析出epoch和ZXID,然后向Leader反饋一個ACKEPOCH響應。
9. 數據同步。Leader收到Learner的ACKEPOCH后,即可進行數據同步。
10. 啟動Leader和Learner服務器。當有過半Learner已經完成了數據同步,那么Leader和Learner服務器實例就可以啟動了。
5. Leader和Follower啟動
1. 創建啟動會話管理器。
2. 初始化Zookeeper請求處理鏈,集群模式的每個處理器也會在啟動階段串聯請求處理鏈。
3. 注冊JMX服務。
至此,集群版的Zookeeper服務器啟動完畢。
三、總結
本篇博文分析了Zookeeper服務端的啟動的詳細細節,之后會給出具體的代碼分析。也謝謝各位園友的觀看~