zookeeper系列之通信模型

本文的主題就是講解Zookeeper通信模型,本節將通過一個概要圖來說明Zookeeper的通信模型。

 

 

Zookeeper的通信架構

在Zookeeper整個系統中,有3中角色的服務,client、Follower、leader。其中client負責發起應用的請求,Follower接受client發起的請求,參與事務的確認過程,在leader crash後的leader選擇。而leader主要承擔事務的協調,當然leader也可以承擔接收客戶請求的功能,爲了方便描述,後面的描述都是client與Follower之間的通信,如果Zookeeper的配置支持leader接收client的請求,client與leader的通信跟client與Follower的通信模式完全一樣。Follower與leader之間的角色可能在某一時刻進行轉換。一個Follower在leader crash掉以後可能被集羣(Quorum)的Follower選舉爲leader。而一個leader在crash後,再次加入集羣(Quorum)將作爲Follower角色存在。在一個集羣(Quorum)中,除了在選舉leader的過程中沒有Follower和leader的區分外,其他任何時刻都只有1個leader和多個Follower。Client、Follower和leader之間的通信架構如下:

 

Client與Follower之間

爲了使客戶端具有較高的吞吐量,Client與Follower之間採用NIO的通信方式。當client需要與Zookeeper service打交道時,首先讀取配置文件確定集羣內的所有server列表,按照一定的load balance算法選取一個Follower作爲一個通信目標。這樣client和Follower之間就有了一條由NIO模式構成的通信通道。這條通道會一直保持到client關閉session或者因爲client或Follower任一方因某種原因異常中斷通信連接。正常情況下, client與Follower在沒有請求發起的時候都有心跳檢測。

 

 

 

 Follower與leader之間

Follower與leader之間的通信主要是因爲Follower接收到像(create, delete, setData, setACL, createSession, closeSession, sync)這樣一些需要讓leader來協調最終結果的命令,將會導致Follower與leader之間產生通信。由於leader與Follower之間的關係式一對多的關係,非常適合client/server模式,因此他們之間是採用c/s模式,由leader創建一個socket server,監聽各Follower的協調請求。

 

 集羣在選擇leader過程中

由於在選擇leader過程中沒有leader,在集羣中的任何一個成員都需要與其他所有成員進行通信,當集羣的成員變得很大時,這個通信量是很大的。選擇leader的過程發生在Zookeeper系統剛剛啓動或者是leader失去聯繫後,選擇leader過程中將不能處理用戶的請求,爲了提高系統的可用性,一定要儘量減少這個過程的時間。選擇哪種方式讓他們可用快速得到選擇結果呢?Zookeeper在這個過程中採用了策略模式,可用動態插入選擇leader的算法。系統默認提供了3種選擇算法,AuthFastLeaderElection,FastLeaderElection,LeaderElection。其中AuthFastLeaderElection和LeaderElection採用UDP模式進行通信,而FastLeaderElection仍然採用tcp/ip模式。在Zookeeper新的版本中,新增了一個learner角色,減少選擇leader的參與人數。使得選擇過程更快。一般說來Zookeeper leader的選擇過程都非常快,通常<200ms。

 

Zookeeper的通信流程

要詳細瞭解Zookeeper的通信流程,我們首先得了解Zookeeper提供哪些客戶端的接口,我們按照具有相同的通信流程的接口進行分組:

 

Zookeeper系統管理命令

Zookeeper的系統管理接口是指用來查看Zookeeper運行狀態的一些命令,他們都是具有4字母構成的命令格式。主要包括:

  1. ruok:發送此命令可以測試zookeeper是否運行正常。
  2. dump:dump server端所有存活session的Ephemeral(臨時)node信息。
  3. stat:獲取連接server的服務器端的狀態及連接該server的所有客服端的狀態信息。
  4. reqs: 獲取當前客戶端已經提交但還未返回的請求。
  5. stmk:開啓或關閉Zookeeper的trace level.
  6. gtmk:獲取當前Zookeeper的trace level是否開啓。
  7. envi: 獲取Zookeeper的java相關的環境變量。
  8. srst:重置server端的統計狀態

當用戶發送這些命令的到server時,由於這些請求只與連接的server相關,沒有業務處理邏輯,非常簡單。Zookeeper對這些命令採用最快的效率進行處理。這些命令發送到server端只佔用一個4字節的int類型來表示不同命令,沒有采用字符串處理。當服務器端接收到這些命令,立刻返回結果。

 

Session創建

任何客戶端的業務請求都是基於session存在的前提下。Session是維持client與Follower之間的一條通信通道,並維持他們之間從創建開始後的所有狀態。當啓動一個Zookeeper client的時候,首先按照一定的算法查找出follower, 然後與Follower建立起NIO連接。當連接建立好後,發送create session的命令,讓server端爲該連接創建一個維護該連接狀態的對象session。當server收到create session命令,先從本地的session列表中查找看是否已經存在有相同sessionId,則關閉原session重新創建新的session。創建session的過程將需要發送到Leader,再由leader通知其他follower,大部分Follower都將此操作記錄到本地日誌再通知leader後,leader發送commit命令給所有Follower,連接客戶端的Follower返回創建成功的session響應。Leader與Follower之間的協調過程將在後面的做詳細講解。當客戶端成功創建好session後,其他的業務命令就可以正常處理了。

 

Zookeeper查詢命令

Zookeeper查詢命令主要用來查詢服務器端的數據,不會更改服務器端的數據。所有的查詢命令都可以即刻從client連接的server立即返回,不需要leader進行協調,因此查詢命令得到的數據有可能是過期數據。但由於任何數據的修改,leader都會將更改的結果發佈給所有的Follower,因此一般說來,Follower的數據是可以得到及時的更新。這些查詢命令包括以下這些命令:

  1. exists:判斷指定path的node是否存在,如果存在則返回true,否則返回false.
  2. getData:從指定path獲取該node的數據
  3. getACL:獲取指定path的ACL。
  4. getChildren:獲取指定path的node的所有孩子結點。

所有的查詢命令都可以指定watcher,通過它來跟蹤指定path的數據變化。一旦指定的數據發生變化(create,delete,modified,children_changed),服務器將會發送命令來回調註冊的watcher. Watcher詳細的講解將在Zookeeper的Watcher中單獨講解。

 

Zookeeper修改命令

Zookeeper修改命令主要是用來修改節點數據或結構,或者權限信息。任何修改命令都需要提交到leader進行協調,協調完成後才返回。修改命令主要包括:

  1. 1.   createSession:請求server創建一個session
  2. 2.   create:創建一個節點
  3. 3.   delete:刪除一個節點
  4. 4.   setData:修改一個節點的數據
  5. 5.   setACL:修改一個節點的ACL
  6. 6.   closeSession:請求server關閉session

我們根據前面的通信圖知道,任何修改命令都需要leader協調。 在leader的協調過程中,需要3次leader與Follower之間的來回請求響應。並且在此過程中還會涉及事務日誌的記錄,更糟糕的情況是還有take snapshot的操作。因此此過程可能比較耗時。但Zookeeper的通信中最大特點是異步的,如果請求是連續不斷的,Zookeeper的處理是集中處理邏輯,然後批量發送,批量的大小也是有控制的。如果請求量不大,則即刻發送。這樣當負載很大時也能保證很大的吞吐量,時效性也在一定程度上進行了保證。

 

zookeeper server端的業務處理-processor鏈

 

<!--EndFragment-->

Zookeeper通過鏈式的processor來處理業務請求,每個processor負責處理特定的功能。不同的Zookeeper角色的服務器processor鏈是不一樣的,以下分別介紹standalone Zookeeper server, leader和Follower不同的processor鏈。

 

Zookeeper中的processor

  1. AckRequestProcessor:當leader從向Follower發送proposal後,Follower將發送一個Ack響應,leader收到Ack響應後,將會調用這個Processor進行處理。它主要負責檢查請求是否已經達到了多數Follower的確認,如果滿足條件,則提交commitProcessor進行commit處理
  2. CommitProcessor:從commited隊列中處理已經由leader協調好並commit的請求或者從請求隊列中取出那些無需leader協調的請求進行下一步處理。
  3. FinalRequestProcessor:任何請求的處理都需要經過這個processor,這是請求處理的最後一個Processor,主要負責根據不同的請求包裝不同的類型的響應包。當然Follower與leader之間協調後的請求由於沒有client連接,將不需要發送響應(代碼體現在if (request.cnxn == null) {return;})。
  4. FollowerRequestProcessor:Follower processor鏈上的第一個,主要負責將修改請求和同步請求發往leader進行協調。
  5. PrepRequestProcessor:在leader和standalone server上作爲第一Processor,主要作用對於所有的修改命令生成changelog。
  6. ProposalRequestProcessor:leader用來將請求包裝爲proposal向Follower請求確認。
  7. SendAckRequestProcessor:Follower用來向leader發送Ack響應的處理。
  8. SyncRequestProcessor:負責將已經commit的事務寫到事務日誌以及take snapshot.
  9. ToBeAppliedRequestProcessor:負責將tobeApplied隊列的中request轉移到下一個請求進行處理。

 

Standalone zookeeper processor鏈

 

 

 

Leader processor鏈

 

Follower processor鏈

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章