分佈式助手Zookeeper

Zookeeper的Session: 
(1)客戶端和server間採用長連接 
(2)連接建立後,server產生session ID(64位)返還給客戶端 
(3)客戶端定期發送ping包來檢查和保持和server的連接 
(4)一旦session結束或超時,所有ephemeral節點會被刪除 
(5)客戶端可根據情況設置合適的session超時時間 

Zookeeper的Watchs: 
Watch是客戶端安裝在server的事件偵聽方法 
(1) 當偵聽的變化發生時,server發消息給客戶端進行通知 
(2) 客戶端使用單線程對所有事件按順序同步回調 
(3) 觸發回調條件: 
• 客戶端連接、斷開連接 
• 節點數據發生改變 
• 節點本身發生變化 
(4)Watch是單發的,每次觸發後會被自動刪除 
(5)如果需要再次偵聽事件,必須重新安裝watch 
(6)無法保證跟蹤到每一個變化 
(7)避免安裝大量watches偵聽在同一個節點 

Zookeeper的一些注意事項: 
在客戶端事件回調實現有阻塞調用 
• 試圖跟蹤每個狀態變化 
• 大量watch偵聽同一個znode的狀態變化 
• 客戶端會有需要長時間處理的GC(garbage collection) 
• Session超時後上層應用不進行恢復處理 


可以把zookper看成一個文件系統,文件系統中的所有文件形成一個數狀結構,zookeeper維護着這樣的樹形層次結構,樹中的節點稱爲znode。每個znode有一個與之相關聯的ACL(Access Control List) 
znode通過路徑被引用,而且要採用絕對路徑,即必須以/開頭。znode存儲的數據要小於1M,這個可以配置,建議不要存儲太大的東西,避免同步操作時間過長。 
znode類型 
短暫znode:回話結束,zookeeper就會把短暫znode刪除,短暫znode不可以有子節點。 
持久znode:回話結束也不會被刪除,除非客戶端明確要刪除此znode,持久znode可以有子節點。 
對於在特定時刻需要知道有哪些分佈式資源可用的應用來說,使用短暫znode比較合適。 

znode的觀察機制 
znode以某種方式發生變化時,“觀察”(watch)機制可以讓客戶端得到通知。可以針對ZooKeeper服務的“操作”來設置觀察,該服務的其他操作可以觸發觀察。比如,客戶端可以對某個客戶端調用exists操作,同時在它上面設置一個觀察,如果此時這個znode不存在,則exists返回false,如果一段時間之後,這個znode被其他客戶端創建,則這個觀察會被觸發,之前的那個客戶端就會得到通知。 

zookeeper的一些基本操作如下: 

<table class="bbcode"><tr><td>操作</td><td>描述<tr><td>create</td><td>創建一個znode(必須有父節點)<tr><td>delete</td><td>刪除一個znode(該znode不能有任何子節點)<tr><td>exists</td><td>測試一個znode是否存在,並且查詢它的元數據<tr><td>getACL,setACL</td><td>獲取/設置一個znode的ACL<tr><td>getChildren</td><td>獲取一個znode的子節點名字列表<tr><td>getData,setData</td><td>獲取/設置一個znode所保存的數據<tr><td>sync</td><td>將客戶端的znode視圖與ZooKeeper服務端同步</table> 

Zookeeper中的更新操作是有條件的。在使用delete或者setData操作時必須提供被更新znode的版本號,如果版本號不匹配,則更新操作失敗。一般情況下設置-1即可。 


API 
目前主要有java和C兩種客戶端,每種操作都有同步和異步兩種執行方式。 
觀察觸發器 
可以設置觀察的操作:exists,getChildren,getData 
可以觸發觀察的操作:create,delete,setData 
下面給出一些事件截圖: 

 

 

 

 

NodeCreated:節點創建事件 
NodeDeleted:節點被刪除事件 
NodeDataChanged:節點數據改變事件 
NodeChildrenChanged:節點的子節點改變事件 

下面我們再來看下ACL(zookeeper的訪問控制列表),每個znode被創建時都會帶有一個ACL列表,用於決定誰可以對它執行何種操作。 

<table class="bbcode"><tr><td>ACL權限</td><td>允許的操作<tr><td>CREATE</td><td>創建節點create("name")<tr><td>READ</td><td>getChildren()  getData()<tr><td>WRITE</td><td>setData<tr><td>DELETE</td><td>delete("name")刪除節點<tr><td>ADMIN</td><td>setACL()設置權限</table> 
每個ACL都是身份驗證模式、符合該模式的一個身份和一組權限的組合。身份驗證模式有三種: 
digest:用戶名,密碼 

host:通過客戶端的主機名來識別客戶端 

ip: 通過客戶端的ip來識別客戶端 

所以我們可以類似這樣構建一個ACL類: 
new ACL(Perms.READ,new Id("host","example.com")); 
這個ACL對應的身份驗證模式是host 
符合該模式的身份是example.com 
權限的組合是:READ 

下面給出一個API連接zookeeper的示例: 
<pre name="code" class="java">package com.util; 

import java.util.concurrent.CountDownLatch; 

import org.apache.zookeeper.WatchedEvent; 
import org.apache.zookeeper.Watcher; 
import org.apache.zookeeper.ZooKeeper; 

/** 
* 測試zookeeper的連接 
* @author 三劫散仙 

* ***/ 
public class Test { 



public static void main(String[] args)throws Exception { 



ZooKeeper  zk=new ZooKeeper("10.2.143.5:2181", 5000, new Watcher() { 
CountDownLatch down=new CountDownLatch(1);//同步阻塞狀態 
@Override 
public void process(WatchedEvent event) { 
if(event.getState()==Event.KeeperState.SyncConnected){ 
down.countDown();//連接上之後,釋放計數器 



}); 

System.out.println("連接成功:"+zk.toString()); 
zk.close();//關閉連接 



</pre> 
打印效果如下: 

<pre name="code" class="java">連接成功:State:CONNECTING sessionid:0x0 local:null remoteserver:null lastZxid:0 xid:1 sent:0 recv:0 queuedpkts:0 pendingresp:0 queuedevents:0 
</pre> 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章