摘要
本節(jié)結(jié)合源碼對集群版服務(wù)器啟動進行概述,流程圖如下
主要分為
預(yù)啟動
初始化
Leader選舉(選舉算法在之后講)
Leader和Follower啟動期交互過程
Leader和Follower啟動
這里都是概述意荤,沒有詳細分析源碼,下面幾節(jié)展開分析
預(yù)啟動
1. 統(tǒng)一由QuorumPeerMain作為啟動類趴泌。
2. 解析配置文件zoo.cfg愉舔。
3. 創(chuàng)建并啟動歷史文件清理器DatadirCleanupFactory育勺。
4. 判斷當前是集群模式還是單機模式的啟動。
在集群模式中怀浆,在zoo.cfg文件中配置了多個服務(wù)器地址扬蕊,可以選擇集群啟動肤粱。
上述代碼都在org.apache.zookeeper.server.quorum.QuorumPeerMain#initializeAndRun中,截圖如下
初始化
1. 創(chuàng)建ServerCnxnFactory厨相。
2. 初始化ServerCnxnFactory。
3. 創(chuàng)建Zookeeper數(shù)據(jù)管理器FileTxnSnapLog鸥鹉。
4. 創(chuàng)建QuorumPeer實例蛮穿。
Quorum是集群模式下特有的對象,是Zookeeper服務(wù)器實例(ZooKeeperServer)的托管者毁渗,QuorumPeer代表了集群中的一臺機器
在運行期間践磅,QuorumPeer會不斷檢測當前服務(wù)器實例的運行狀態(tài),同時根據(jù)情況發(fā)起Leader選舉灸异。
5. 創(chuàng)建內(nèi)存數(shù)據(jù)庫ZKDatabase府适。
ZKDatabase負責管理ZooKeeper的所有會話記錄以及DataTree和事務(wù)日志的存儲羔飞。
6. 初始化QuorumPeer。
將核心組件如FileTxnSnapLog檐春、ServerCnxnFactory逻淌、ZKDatabase注冊到QuorumPeer中,同時配置QuorumPeer的參數(shù)疟暖,如服務(wù)器列表地址卡儒、Leader選舉算法和會話超時時間限制等。
7. 恢復(fù)本地數(shù)據(jù)俐巴。
8. 啟動ServerCnxnFactory主線程骨望。
其中1-6步在org.apache.zookeeper.server.quorum.QuorumPeerMain#runFromConfig中,順序不完全一樣
7-8步在org.apache.zookeeper.server.quorum.QuorumPeer#start中
@Override
public synchronized void start() {
loadDataBase();//從事務(wù)日志目錄dataLogDir和數(shù)據(jù)快照目錄dataDir中恢復(fù)出DataTree數(shù)據(jù)
cnxnFactory.start();//開啟對客戶端的連接端口,啟動ServerCnxnFactory主線程
startLeaderElection();//創(chuàng)建出選舉算法
super.start();//啟動QuorumPeer線程欣舵,在該線程中進行服務(wù)器狀態(tài)的檢查
}
leader選舉
1. 初始化Leader選舉算法
集群模式特有擎鸠,Zookeeper首先會根據(jù)自身的服務(wù)器ID(SID)、最新的ZXID(lastLoggedZxid)和當前的服務(wù)器epoch(currentEpoch)來生成一個初始化投票
在初始化過程中缘圈,每個服務(wù)器都會給自己投票劣光。然后,根據(jù)zoo.cfg的配置准验,創(chuàng)建相應(yīng)Leader選舉算法實現(xiàn)
Zookeeper提供了三種默認算法(LeaderElection赎线、AuthFastLeaderElection、FastLeaderElection)糊饱,可通過zoo.cfg中的electionAlg屬性來指定垂寥,但現(xiàn)只支持FastLeaderElection選舉算法。
在初始化階段另锋,Zookeeper會創(chuàng)建Leader選舉所需的網(wǎng)絡(luò)I/O層QuorumCnxManager滞项,同時啟動對Leader選舉端口的監(jiān)聽,等待集群中其他服務(wù)器創(chuàng)建連接夭坪。
源碼在QuorumPeer#startLeaderElection中
完成自己的投票以及投票算法的獲取
2.注冊JMX服務(wù)文判。
代碼在org.apache.zookeeper.server.quorum.QuorumPeer#run中
3.檢測當前服務(wù)器狀態(tài)
運行期間,QuorumPeer會不斷檢測當前服務(wù)器狀態(tài)室梅。在正常情況下戏仓,Zookeeper服務(wù)器的狀態(tài)在LOOKING、LEADING亡鼠、FOLLOWING/OBSERVING之間進行切換赏殃。在啟動階段,QuorumPeer的初始狀態(tài)是LOOKING间涵,因此開始進行Leader選舉仁热。
4. Leader選舉。
通過投票確定Leader勾哩,其余機器稱為Follower和Observer抗蠢。具體算法在后面會給出举哟。
源碼體現(xiàn)在org.apache.zookeeper.server.quorum.Election#lookForLeader
默認實現(xiàn)org.apache.zookeeper.server.quorum.FastLeaderElection#lookForLeader
上述步驟在
2-4的源碼步驟太長了,這里不貼出來了迅矛,就在QuorumPeer#run中
Leader和Follower啟動期交互過程
創(chuàng)建Leader服務(wù)器和Follower服務(wù)器妨猩。完成Leader選舉后扳埂,每個服務(wù)器會根據(jù)自己服務(wù)器的角色創(chuàng)建相應(yīng)的服務(wù)器實例趋急,并進入各自角色的主流程同欠。
源碼體現(xiàn)在org.apache.zookeeper.server.quorum.QuorumPeer#run
中switch不同的case
1.Leader服務(wù)器啟動Follower接收器LearnerCnxAcceptor(leader端)
運行期間漠嵌,Leader服務(wù)器需要和所有其余的服務(wù)器(統(tǒng)稱為Learner)保持連接以確集群的機器存活情況湾揽,LearnerCnxAcceptor負責接收所有非Leader服務(wù)器的連接請求珍策。
2.Learner服務(wù)器開始和Leader建立連接劝萤。(learner端)
所有Learner會找到Leader服務(wù)器吵血,并與其建立連接票堵。
3.Leader服務(wù)器創(chuàng)建LearnerHandler(leader端)
Leader接收到來自其他機器連接創(chuàng)建請求后扼睬,會創(chuàng)建一個LearnerHandler實例,每個LearnerHandler實例都對應(yīng)一個Leader與Learner服務(wù)器之間的連接悴势,其負責Leader和Learner服務(wù)器之間幾乎所有的消息通信和數(shù)據(jù)同步窗宇。
4.向Leader注冊(learner端)
Learner完成和Leader的連接后,會向Leader進行注冊特纤,即將Learner服務(wù)器的基本信息(LearnerInfo)军俊,包括SID和ZXID,發(fā)送給Leader服務(wù)器捧存。
5.Leader解析Learner信息粪躬,計算新的epoch(leader端)
Leader接收到Learner服務(wù)器基本信息后,會解析出該Learner的SID和ZXID昔穴,然后根據(jù)ZXID解析出對應(yīng)的epoch_of_learner镰官,并和當前Leader服務(wù)器的epoch_of_leader進行比較,如果該Learner的epoch_of_learner更大吗货,則更新Leader的epoch_of_leader = epoch_of_learner + 1泳唠。然后LearnHandler進行等待,直到過半Learner已經(jīng)向Leader進行了注冊宙搬,同時更新了epoch_of_leader后笨腥,Leader就可以確定當前集群的epoch了。
6.發(fā)送Leader狀態(tài)勇垛。(leader端)
計算出新的epoch后扇雕,Leader會將該信息以一個LEADERINFO消息的形式發(fā)送給Learner,并等待Learner的響應(yīng)窥摄。
7.Learner發(fā)送ACK消息。(learner端)
Learner接收到LEADERINFO后础淤,會解析出epoch和ZXID崭放,然后向Leader反饋一個ACKEPOCH響應(yīng)哨苛。
8.數(shù)據(jù)同步(leader端)
Leader收到Learner的ACKEPOCH后,即可進行數(shù)據(jù)同步币砂。
9.啟動Leader和Learner服務(wù)器建峭。(learner和leader)
當有過半Learner已經(jīng)完成了數(shù)據(jù)同步,那么Leader和Learner服務(wù)器實例就可以啟動了决摧。
源碼部分
leader部分在 org.apache.zookeeper.server.quorum.Leader#lead
follower部分在 org.apache.zookeeper.server.quorum.Follower#followLeader
Leader和Follower啟動
1. 創(chuàng)建啟動會話管理器亿蒸。
2. 初始化Zookeeper請求處理鏈,集群模式的每個處理器也會在啟動階段串聯(lián)請求處理鏈掌桩。
3. 注冊JMX服務(wù)边锁。
對應(yīng)的代碼在
Learner#syncWithLeader 調(diào)用 ZooKeeperServer#startup
Leader#startZkServer 調(diào)用 ZooKeeperServer#startup
思考
何時進行l(wèi)eader選舉的
QuorumPeer#run中,初始狀態(tài)是LOOKING
因此調(diào)用了
setCurrentVote(makeLEStrategy().lookForLeader());
的邏輯波岛,lookForLeader就根據(jù)選舉算法產(chǎn)生了leader茅坛,具體算法過程之后再講
選舉算法中,目前只支持FastLeaderElection,體現(xiàn)在哪
org.apache.zookeeper.server.quorum.QuorumPeerConfig#electionAlg
值固定為3
然后解析config的時候
org.apache.zookeeper.server.quorum.QuorumPeerMain#runFromConfig
執(zhí)行
quorumPeer.setElectionType(config.getElectionAlg());
也就是quorumPeer的ElectionAlg是3
然后創(chuàng)建選舉算法時
org.apache.zookeeper.server.quorum.QuorumPeer#startLeaderElection
org.apache.zookeeper.server.quorum.QuorumPeer#createElectionAlgorithm
帶入的參數(shù)也就是3
進入
問題
leader創(chuàng)立之后怎么知道learner的地址是什么则拷,否則LearnerCnxAcceptor怎么接收所有非Leader服務(wù)器的連接請求
沒看出來哪里體現(xiàn)贡蓖,也就是說我可以外部搞一個端口來完成和leader的交互?煌茬?斥铺?
refer
http://www.cnblogs.com/leesf456/p/6105276.html
https://my.oschina.net/xianggao/blog/538746
《paxos到zk》