一、zkClient使用的原因
1)zookeeper原生API使用中,經常會遇到session expire這類異常,異常發生後需要進行重新串連,重建立立session,會比較麻煩
2)zookeeper的watcher機制是一次性的,如果你想訂閱節點的狀態變化、子節點變化等,每次在處理完變化事件之後,需要重新註冊watcher。可想而知這是一件令人絕望的事情。這個特性使得在處理事件和重新加上watcher這段時間發生的節點變化將無法被感知。
3)zookeeper的API介面中,節點資料預設為二進位byte數組,如果想直接儲存物件類型的資料,需要相關的序列化工作。
以上問題,zkClient可以很好的解決。
二、引入依賴
ZkClient目前有兩個不同artifactId的系列。
其中最早的0.1版本maven依賴如下:
<dependency> <groupId>com.github.sgroschupf</groupId> <artifactId>zkclient</artifactId> <version>0.1</version> </dependency>
另外一個系列為的maven依賴為:
<dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>0.10</version></dependency>
源碼地址
三、使用
在使用zkClient之前,需要先執行個體化一個zkClient對象,指定zookeeper地址以及逾時時間。
ZkClient zkClient=new ZkClient("localhost:2181",2000);
簡單一實例(與zookeeper原生API大同小異)
//建立節點 zkClient.createPersistent("/docRoot"); //建立子節點 zkClient.createPersistent("/docRoot/child","child data"); //獲得子節點 List<String> childList=zkClient.getChildren("/docRoot"); //獲得子節點個數 int childCount=zkClient.countChildren("/docRoot"); //判斷節點是否存在 boolean flag=zkClient.exists("/docRoot/child"); //寫入節點資料 zkClient.writeData("/docRoot/child","child data changed"); //讀取節點資料 Object obj=zkClient.readData("/docRoot/child"); //刪除節點(刪除父節點之前,需要刪除其子節點) zkClient.delete("/docRoot/child2");
zkClient將zookeeper的watcher機制轉換為一種更加容易理解的訂閱形式,並且這種關係是可以保持的,而非一次性的。也就是說,當watcher使用完後,zkclient會自動再增加一個相同的watcher。zkClient將變化事件重新定義為可供訂閱的三種狀態,一類是子節點的變化,一類是資料的變化,還有一類是狀態的變化。
1)訂閱子節點狀態的變化
zkClient.subscribeChildChanges("/docRoot", new IZkChildListener() { public void handleChildChange(String parentPath, List<String> list) throws Exception { String s=""; for(String str:list){ s+=str+","; } System.out.println("子節點變化:"+s); } });
2)訂閱節點資料的變化
zkClient.subscribeDataChanges("/docRoot", new IZkDataListener() { public void handleDataChange(String dataPath, Object data) throws Exception { System.out.println("節點資料變化:"+dataPath+"-資料:"+data.toString()); } public void handleDataDeleted(String dataPath) throws Exception { System.out.println("節點資料刪除:"+dataPath); }});
3)訂閱節點串連及狀態的變化情況
zkClient.subscribeStateChanges(new IZkStateListener() { public void handleStateChanged(Watcher.Event.KeeperState keeperState) throws Exception { System.out.println("節點串連及狀態變化:"+keeperState.name()); } public void handleNewSession() throws Exception { System.out.println("節點Session變化。。。"); }});
當發生session expire異常進行重連時,由於原來的所有watcher和EPHEMERAL節點都已失效,可以在handleNewSession方法中進行相應的容錯處理