Zookeeper的Session
出處:http://www.iteye.com
介紹一下基于zookeeper的一些API的編程。
在此之前,我們先來熟悉一下相關知識:
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的一些基本操作如下:
操作 | 描述 | create | 創建一個znode(必須有父節點) | delete | 刪除一個znode(該znode不能有任何子節點) | exists | 測試一個znode是否存在,并且查詢它的元數據 | getACL,setACL | 獲取/設置一個znode的ACL | getChildren | 獲取一個znode的子節點名字列表 | getData,setData | 獲取/設置一個znode所保存的數據 | sync | 將客戶端的znode視圖與ZooKeeper服務端同步 |
Zookeeper中的更新操作是有條件的。在使用delete或者setData操作時必須提供被更新znode的版本號,如果版本號不匹配,則更新操作失敗。一般情況下設置-1即可。
API
目前主要有java和C兩種客戶端,每種操作都有同步和異步兩種執行方式。
觀察觸發器
可以設置觀察的操作:exists,getChildren,getData
可以觸發觀察的操作:create,delete,setData
下面給出一些事件截圖:




NodeCreated:節點創建事件
NodeDeleted:節點被刪除事件
NodeDataChanged:節點數據改變事件
NodeChildrenChanged:節點的子節點改變事件
下面我們再來看下ACL(zookeeper的訪問控制列表),每個znode被創建時都會帶有一個ACL列表,用于決定誰可以對它執行何種操作。
ACL權限 | 允許的操作 | CREATE | 創建節點create("name") | READ | getChildren() getData() | WRITE | setData | DELETE | delete("name")刪除節點 | ADMIN | setACL()設置權限 |
每個ACL都是身份驗證模式、符合該模式的一個身份和一組權限的組合。身份驗證模式有三種:
digest:用戶名,密碼
host:通過客戶端的主機名來識別客戶端
ip: 通過客戶端的ip來識別客戶端
所以我們可以類似這樣構建一個ACL類:
new ACL(Perms.READ,new Id("host","example.com"));
這個ACL對應的身份驗證模式是host
符合該模式的身份是example.com
權限的組合是:READ
下面給出一個API連接zookeeper的示例:



- 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();//關閉連接
- }
- }
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();//關閉連接 } }
打印效果如下:



- 連接成功:State:CONNECTING sessionid:0x0 local:null remoteserver:null lastZxid:0 xid:1 sent:0 recv:0 queuedpkts:0 pendingresp:0 queuedevents:0
ITeye推薦