Zookeeper服務框架之介紹篇
Zookeeper是一種分佈式服務框架,是apache hadoop的子項目,完全開源存在,它的誕生主要用來處理分佈式環境中數據管理問題,比如:分佈式應用程序配置、集羣管理、狀態同步服務及命名服務等。這裏,我們以3.4.8版本爲例展開介紹,其最新的版本下載可以從地址:
http://hadoop.apache.org/zookeeper/ 中獲取,並以java項目爲例進行分析和使用Zookeeper,和以往文章一樣,都是以安裝配置開始!
l 安裝配置
l 組件特點
l 入門使用
一、安裝配置
Zookeeper的安裝十分簡單,我們只需要從如下地址下載並解壓:
http://mirrors.cnnic.cn/apache/zookeeper/
然後,Zookeeper的安裝配置,可以從單機和集羣環境介紹:
1、配置
在開始服務前,有幾個基本配置要準備下,Zookeeper的配置文件在conf文件夾下,默認名爲zoo_sample.cfg,也是Zookeeper默認加載的配置文件,這裏我們把它改個名字:
$sudo mv zoo_sample.cfg zoo.cfg
另外,當前版本的Zookeeper的conf下,還有log4j.properties和configuration.xsl文件,在後續文章中會陸續介紹它們的作用,那麼接下來就先介紹zoo.cfg配置和使用情況。
2、單機環境
在單機環境下,滿足服務基本需求的zoo.cfg基本內容如下:
tickTime=2000
dataDir=/zookeeper/zookeeper/build
clientPort=2181
參數說明:
tickTime:Zookeeper服務器間或客戶端與服務器之間維持心跳的間隔時間,即每隔tickTime時間,就發送一次心跳檢測。
dataDir:Zookeeper服務保存數據的位置,默認也是其存放寫入數據的日誌文件的位置。
clientPort:Zookeeper會監聽這個端口,來知道客戶端鏈接到它,也就是客戶端鏈接Zookeeper服務器的端口。
當配置好之後,我們可以啓動Zookeeper服務了,具體如下:
$sudo ./zkServer.sh start
啓動的結果:
3、集羣環境
Zookeeper不僅可以單機提供服務,同時也支持多機組成集羣來提供服務。實際上 Zookeeper還支持另外一種僞集羣的方式,也就是可以在一臺物理機上運行多個Zookeeper 實例,下面將介紹集羣模式的安裝和配置。
Zookeeper的集羣模式的安裝和配置也不是很複雜,所要做的就是增加幾個配置項。集羣模式除了上面的三個配置項還要增加下面幾個配置項:
initLimit=5
syncLimit=2
server.1=192.168.211.1:2888:3888
server.2=192.168.211.2:2888:3888
• initLimit:這個配置項是用來配置 Zookeeper接受客戶端(這裏所說的客戶端不是用戶連接 Zookeeper 服務器的客戶端,而是 Zookeeper 服務器集羣中連接到Leader 的 Follower 服務器)初始化連接時最長能忍受多少個心跳時間間隔數。當已經超過5 個心跳的時間(也就是 tickTime)長度後 Zookeeper 服務器還沒有收到客戶端的返回信息,那麼表明這個客戶端連接失敗。總的時間長度就是 5*2000=10 秒
• syncLimit:這個配置項標識 Leader與 Follower 之間發送消息,請求和應答時間長度,最長不能超過多少個tickTime 的時間長度,總的時間長度就是 2*2000=4 秒
• server.A=B:C:D:其中 A 是一個數字,表示這個是第幾號服務器;B 是這個服務器的 ip 地址;C 表示的是這個服務器與集羣中的 Leader 服務器交換信息的端口;D 表示的是萬一集羣中的 Leader 服務器掛了,需要一個端口來重新進行選舉,選出一個新的 Leader,而這個端口就是用來執行選舉時服務器相互通信的端口。如果是僞集羣的配置方式,由於 B 都是一樣,所以不同的 Zookeeper 實例通信端口號不能一樣,所以要給它們分配不同的端口號。
除了修改 zoo.cfg 配置文件,集羣模式下還要配置一個文件 myid,這個文件在 dataDir 目錄下,這個文件裏面就有一個數據就是 A 的值,Zookeeper 啓動時會讀取這個文件,拿到裏面的數據與 zoo.cfg 裏面的配置信息比較從而判斷到底是那個 server。
NOTE:
停止:zkServer.shstop
重啓:zkServer.shrestart
啓動: zkServer.sh start
二、組件特點
1、數據結構
Zookeeper本身提供和維護了一個有層次關係的數據結構,類似標準的文件系統,不同的是Zookeeper文件系統的每個節點znode,都可以存儲數據,而znode目前有四種類型:臨時節點、臨時順序編號節點、持久化節點及持久化順序編號節點,那麼接下來結合網絡上的數據結構圖說明:
特點說明:
A、每個znode節點,都可以擁有子節點,並且都可以存儲數據(除了臨時節點EPHEMERAL);
B、每個znode節點,都被它所在的路徑唯一標註,比如:NameService下的Server1,被唯一的標識爲:/NameService/Server1;
C、每個znode節點,都有版本的,也就是該節點的路徑下,存放多份版本的數據;
D、每個znode節點,都可以自動編號,比如:已經存在App1節點,那麼再創建App1節點時,會自動創建App2節點;
E、每個znode臨時節點,當客戶端與服務端斷開鏈接後,znode也自動被刪除;
F、每個znode節點都可以被監控,包含該節點存放的數據及其子目錄結構或數據被修改時,會立即通知發起該設置的客戶端;
G、客戶端與服務端的鏈接爲長鏈接,彼此間採用心跳方式保持通信,這個鏈接狀態爲session狀態,所以如果某個znode節點爲臨時節點,那麼這個session就不起作用了;
2、工作特點
原理說明:
A、Zookeeper服務核心是原子廣播,它保證了各個參與的Server間同步,實現它協議爲Zab協議,它分爲恢復模式和廣播模式。當服務啓動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和 leader的狀態同步以後,恢復模式就結束了。狀態同步保證了leader和Server具有相同的系統狀態。
B、Zookeeper服務持續監聽所有註冊的znode節點,一旦節點的結構、數據發生變化時,leader節點會監控到變化並更新系統狀態值,所有follower和observer節點,會向leader節點的數據狀態同步,這也是Zookeeper在分佈式環境的核心作用;
C、所有的observer的znode節點,都可接收客戶端的鏈接,也會從leader節點同步更新最新的數據版本,但其不參與leader的投票動作,會將客戶端的寫入數據請求轉發給leader節點處理;
D、所有的follower的znode節點,都有資格參與leader的投票選擇,也會自動從leader節點更新同步數據版本,也處理客戶端的請求及返回結果;
3、設計目的
A、原子性,各個znode節點數據只有更新成功或失敗,沒有中間狀態;
B、可靠性,如果一條消息被一臺服務器接收,那麼其它各個服務器都會接收,保證了數據的一致性;
C、實時性,Zookeeper可保證客戶端將在一個時間間隔範圍內獲得服務器的更新信息,或者服務器失效的信息。但由於網絡延時等原因,Zookeeper不能保證兩個客戶端能同時得到最新的數據,如果需要最新數據,應該在讀取數據之前調用sync()接口,來手動獲取最新的數據版本;
D、等待無關性,無效的或是阻塞的客戶端鏈接,不影響其它任務客戶端鏈接,各個鏈接客戶端彼此獨立鏈接;
E、一致性,客戶端不論連接到哪個服務器上,展示給它都是同一個視圖,這是Zookeeper最重要的性能。
三、如何使用
基本使用如下,比較簡單:
publicstatic void main(String[] args) {
try{
// 創建一個與服務器的連接
ZooKeeper zk = new ZooKeeper("localhost:"+ 2181,
200000, new Watcher() {
// 監控所有被觸發的事件
public voidprocess(WatchedEvent event) {
log("已經觸發了" + event.getType() + "事件!");
}
});
// 創建一個目錄節點
zk.create("/testRootPath", "testRootData".getBytes(),Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
// 創建一個子目錄節點
zk.create("/testRootPath/testChildPathOne","testChildDataOne".getBytes(),
Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
log(new String(zk.getData("/testRootPath",false,null)));
// 取出子目錄節點列表
log(zk.getChildren("/testRootPath",true));
// 修改子目錄節點數據
zk.setData("/testRootPath/testChildPathOne","modifyChildDataOne".getBytes(),-1);
log("目錄節點狀態:["+zk.exists("/testRootPath",true)+"]");
// 創建另外一個子目錄節點
zk.create("/testRootPath/testChildPathTwo","testChildDataTwo".getBytes(),
Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
log(new String(zk.getData("/testRootPath/testChildPathTwo",true,null)));
// 刪除子目錄節點
zk.delete("/testRootPath/testChildPathTwo",-1);
zk.delete("/testRootPath/testChildPathOne",-1);
// 刪除父目錄節點
zk.delete("/testRootPath",-1);
// 關閉連接
zk.close();
}catch (IOException e) {
e.printStackTrace();
}catch (KeeperException | InterruptedException e) {
e.printStackTrace();
}
}
privatestatic void log(Object msg) {
System.out.println(msg);
}
運行結果如下:
分佈式服務框架之Zookeeper就介紹到這裏,由於作者水平有限,如有問題請在評論發言或是QQ羣(245389109(新))討論,謝謝。