zookeeper的Java客戶端API

weixin_34198881發表於2018-06-01

zookeeper作為一個分散式服務框架,主要用來解決分散式資料一致性問題,對多種語言提供了API。這裡主要記錄下JAVA客戶端API的使用。

 

1.建立會話

客戶端可以通過建立一個ZooKeeper例項來連線zookeeper伺服器

ZooKeeper的4個建構函式如下:

 

[java] view plain copy
 
  1. ZooKeeper(connectString, sessionTimeout, watcher);  
  2. ZooKeeper(connectString, sessionTimeout, watcher,canBeReadOnly);  
  3. ZooKeeper(connectString, sessionTimeout, watcher, sessionId, sessionPasswd);  
  4. ZooKeeper(connectString, sessionTimeout, watcher, sessionId, sessionPasswd, canBeReadOnly);  

 


 

引數說明:

connectString: 連線字串 例如 "127.0.0.1:2181"

sessionTimeout: 會話超時時間 以毫秒為單位的整型值 在sessionTimeout時間內服務端與客戶端沒有有效的心跳檢測 則會話失效

watcher: 預設的事件通知處理器

sessionId: 會話ID

sessionPasswd: 會話祕鑰

canBeReadOnly: 是否是隻讀  

      

[java] view plain copy
 
  1. public class ZookeeperSampleTest implements Watcher {  
  2.   
  3.     private static CountDownLatch connectedSemaphore = new CountDownLatch(1);  
  4.       
  5.     public static void main(String args[]) throws IOException, InterruptedException{  
  6.         ZooKeeper zk = new ZooKeeper("192.168.1.138:2181",5000,new ZookeeperSampleTest());  
  7.         System.out.println(zk.getState());  
  8.         try {  
  9.             connectedSemaphore.await();  
  10.         } catch (Exception e) {  
  11.             // TODO: handle exception  
  12.         }  
  13.         Long sessionId = zk.getSessionId();  
  14.         byte[] password = zk.getSessionPasswd();  
  15.         zk = new ZooKeeper("192.168.1.138:2181",5000,new ZookeeperSampleTest(),1L,"test".getBytes());  
  16.         zk = new ZooKeeper("192.168.1.138:2181",5000,new ZookeeperSampleTest(),sessionId,password);  
  17.         Thread.sleep(Integer.MAX_VALUE);  
  18.         //System.out.println("ZooKeeper session established");  
  19.     }  
  20.   
  21.     @Override  
  22.     public void process(WatchedEvent event) {  
  23.         // TODO Auto-generated method stub  
  24.         System.out.println("Receive watched event :" + event);  
  25.         if(event.getState()==KeeperState.SyncConnected){  
  26.             connectedSemaphore.countDown();  
  27.         }  
  28.     }  
  29.   
  30. }  

 

 

2.建立節點

建立節點的方式分為同步和非同步,建構函式如下:

 

[java] view plain copy
 
  1. zk.create(path, data, acl, createMode);  
  2. , data, acl, createMode, cb, ctx);  

引數說明:

 

path: 建立節點的路徑 如:/zk-test

data[]: 位元組陣列,節點資料

acl: 許可權  

createMode: 節點型別  分為4種: 永續性節點,永續性有序節點,臨時節點,臨時有序節點

cb: 回撥函式 需要實現StringCallback介面

ctx: 上下文 一般用於回撥函式時候使用

 

[java] view plain copy
 
  1. public class ZookeeperSampleCreateTest implements Watcher {  
  2.   
  3.     public static CountDownLatch connectedSemaphore = new CountDownLatch(1);  
  4.       
  5.     public static void main(String[] args) throws IOException, InterruptedException, KeeperException{  
  6.         ZooKeeper zk = new ZooKeeper("192.168.1.138:2181",5000,new ZookeeperSampleCreateTest());  
  7.         connectedSemaphore.await();  
  8.         /*同步的方式*/  
  9.         /*String path1 = zk.create("/zk-test-ephemeral-", "test-ephemeral".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); 
  10.         System.out.println("Success create node :" + path1); 
  11.         String path2 = zk.create("/zk-test-ephemeral-", "test-ephemeral-sequential".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); 
  12.         System.out.println("Success create node :" + path2);*/  
  13.           
  14.         /*非同步的方式*/  
  15.         zk.create("/zk-test-ephemeral-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,new IStringCallback(),"i am context");  
  16.         zk.create("/zk-test-ephemeral-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL,new IStringCallback(),"i am context");  
  17.         zk.create("/zk-test-ephemeral-", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL,new IStringCallback(),"i am context");  
  18.         Thread.sleep(Integer.MAX_VALUE);  
  19.     }  
  20.       
  21.     @Override  
  22.     public void process(WatchedEvent event) {  
  23.         // TODO Auto-generated method stub  
  24.         if(KeeperState.SyncConnected == event.getState()){  
  25.             connectedSemaphore.countDown();  
  26.         }  
  27.     }  
  28. }  
  29.   
  30. class IStringCallback implements AsyncCallback.StringCallback{  
  31.   
  32.     @Override  
  33.     public void processResult(int rc, String path, Object ctx, String name) {  
  34.         // TODO Auto-generated method stub  
  35.         System.out.println("Create path result: [" + rc + "," + path + "," + ctx + ", real path name " + name);  
  36.     }  
  37.       
  38. }  

 

 

3.刪除節點

 

[java] view plain copy
 
  1. zk.delete(path,version);  
  2. zk.delete(path,version,cb,ctx);  

引數說明:

 

path:節點路徑

version:版本號

cb: 回撥函式

ctx: 上下文

 

4.獲取子節點

getChildren有8個過載方法

 

[java] view plain copy
 
  1.               zk.getChildren(path, watch);  
  2. zk.getChildren(path, watcher);  
  3. zk.getChildren(path, watch, stat);  
  4. zk.getChildren(path, watcher, stat);  
  5. zk.getChildren(path, watch, cb, ctx);  
  6. zk.getChildren(path, watcher, cb, ctx);  

其中 回撥函式有兩種  ChildrenCallback  Children2Callback

 

引數說明:

path:節點路徑

watch: boolean型別 如果為true 表示使用預設的Watcher 為false表示不需要Watcher

watcher: 通知處理器 在本次獲取子節點以後  一旦子節點有變化機會收到服務端傳來的通知

stat: 指定資料節點的節點狀態資訊,傳入一箇舊的stat物件,當執行方法後 stat會被伺服器響應的新stat替換

cb:回撥函式 有兩種型別 上面已經說過

ctx: 上下文

 5.獲取節點資料

獲取節點資料有4個過載方法

 

[java] view plain copy
 
  1.               zk.getData(path, watch, stat);  
  2. zk.getData(path, watcher, stat);  
  3. zk.getData(path, watch, cb, ctx);  
  4. zk.getData(path, watcher, cb, ctx);  

引數說明:

 

path: 節點路徑

watch: boolean型別 如果為true 表示使用預設的Watcher 為false表示不需要Watcher

stat: 指定資料節點的節點狀態資訊,傳入一箇舊的stat物件,當執行方法後 stat會被伺服器響應的新stat替換

cb:回撥函式 有兩種型別 上面已經說過

ctx: 上下文

在獲取節點資料時候 如果註冊watcher 在節點資料傳送變化的時候會通知客戶端,當客戶端收到通知以後,如果想下次資料傳送變化再次收到通知,

需要重新註冊watcher,獲取子節點機制也如此

6.更新節點資料

更新節點資料也分為同步非同步兩個方法

 

[java] view plain copy
 
  1. zk.setData(path, data, version);  
  2. zk.setData(path, data, version, cb, ctx);  

引數說明:同上

 

 

[java] view plain copy
 
  1. public class ZookeeperSampleGetDataTest implements Watcher {  
  2.   
  3.     public static CountDownLatch connectedSemaphore = new CountDownLatch(1);  
  4.       
  5.     public static Stat stat = new Stat();  
  6.       
  7.     public static ZooKeeper zk = null;  
  8.       
  9.     public static void main(String[] args) throws IOException, KeeperException, InterruptedException{  
  10.         String path = "/zk-test";  
  11.         zk = new ZooKeeper("192.168.1.138:2181", 5000, new ZookeeperSampleGetDataTest());  
  12.         connectedSemaphore.await();  
  13.           
  14.         //獲取子節點  
  15.         /*zk.delete(path, 0); 
  16.         zk.create(path, "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); 
  17.         zk.create(path+"/c1", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); 
  18.         //同步方法獲取children 
  19.         //List<String> childs = zk.getChildren(path, true); 
  20.         //System.out.println(childs); 
  21.         //非同步方法獲取children 
  22.         zk.getChildren(path, true, new IChildren2Callback(), null); 
  23.          
  24.         zk.create(path+"/c2", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); 
  25.         Thread.sleep(Integer.MAX_VALUE);*/  
  26.         //獲取節點資料  
  27.         zk.delete(path, 0);  
  28.         zk.create(path, "123".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);  
  29.           
  30.         System.out.println(new String(zk.getData(path, true, stat)));  
  31.         /** czxid: 建立該節點的事務ID  mzxid: 更新該節點的事務ID  version: 資料版本*/  
  32.         System.out.println("Czxid: " + stat.getCzxid() + "Mzxid: " + stat.getMzxid() + "Version: " + stat.getVersion());  
  33.           
  34.         zk.setData(path, "123".getBytes(), -1);  
  35.           
  36.         Thread.sleep(Integer.MAX_VALUE);  
  37.     }  
  38.       
  39.       
  40.     @Override  
  41.     public void process(WatchedEvent event) {  
  42.         // TODO Auto-generated method stub  
  43.         if(KeeperState.SyncConnected==event.getState()){  
  44.             if(EventType.None==event.getType() && null==event.getPath()){  
  45.                 connectedSemaphore.countDown();  
  46.             }else if(event.getType()==EventType.NodeChildrenChanged){  
  47.                 try {  
  48.                     System.out.println("Get Child :" + zk.getChildren(event.getPath(), true));  
  49.                 } catch (KeeperException | InterruptedException e) {  
  50.                     // TODO Auto-generated catch block  
  51.                     e.printStackTrace();  
  52.                 }  
  53.             }else if(event.getType()==EventType.NodeDataChanged){  
  54.                 try {  
  55.                     System.out.println(new String(zk.getData(event.getPath(), true, stat)));  
  56.                     System.out.println("Czxid: " + stat.getCzxid() + "Mzxid: " + stat.getMzxid() + "Version: " + stat.getVersion());  
  57.                 } catch (KeeperException | InterruptedException e) {  
  58.                     // TODO Auto-generated catch block  
  59.                     e.printStackTrace();  
  60.                 }  
  61.             }      
  62.         }  
  63.     }  
  64. }  
  65.   
  66. class IChildren2Callback implements AsyncCallback.Children2Callback{  
  67.   
  68.     @Override  
  69.     public void processResult(int rc, String path, Object ctx,  
  70.             List<String> childrens, Stat stat) {  
  71.         // TODO Auto-generated method stub  
  72.         System.out.println("Get Children znode result: [response code: " + rc + ", param path: " + path + ", ctx " + ctx  
  73.                 + ", childrens :" +  childrens + ", stat: " + stat);  
  74.     }  
  75.       
  76. }  

其中更新節點資料 版本version問題 -1表示基於資料的最新版本更新 這裡可以作為分散式鎖的一個思路 如果客戶端參入的version不是資料最新版本則會更新失敗

 

比如目前節點"/zk-test"的資料版本為 2 而某個客戶端嘗試 執行 setData("/zk-test","test".getBytes(),1) 由於傳入version為1 < 伺服器目前版本2 這樣就會更新失敗

7.檢測節點是否存在

 

[java] view plain copy
 
  1.               zk.exists(path, watch);  
  2. zk.exists(path, watcher);  
  3. zk.exists(path, watch, cb, ctx);  
  4. zk.exists(path, watcher, cb, ctx);  

如果判斷節點是否存在是 註冊watcher 會對節點是否存在進行監聽--建立節點,刪除節點,節點資料更新都會通知客戶端

 

8.許可權控制

zookeeper提供了ACL的許可權控制機制,簡單來說就是通過控制zookeeper伺服器上資料節點的ACL,來控制客戶端對節點的訪問許可權

 

[java] view plain copy
 
  1. addAuthInfo(String scheme,byte[] auth);  

引數說明:

 

scheme: 許可權控制模式 分為: world ,auth,digest,ip和super

auth: 具體的許可權資訊  類似於shiro的許可權字串

如下程式碼:

 

[java] view plain copy
 
  1. <span style="white-space:pre;">     </span>ZooKeeper zk1 = new ZooKeeper("192.168.1.138:2181",5000,new ZookeeperSampleCreateTest());  
  2.         zk1.addAuthInfo("digest", "test:true".getBytes());  
  3.         zk1.create("/zk-test-auth", "123".getBytes(), Ids.CREATOR_ALL_ACL, CreateMode.EPHEMERAL);  
  4.         ZooKeeper zk2 = new ZooKeeper("192.168.1.138:2181",5000,new ZookeeperSampleCreateTest());  
  5.         zk2.addAuthInfo("digest", "test:true".getBytes());  
  6.         System.out.println(new String(zk2.getData("/zk-test-auth", false, null)));  
  7.         ZooKeeper zk3 = new ZooKeeper("192.168.1.138:2181",5000,new ZookeeperSampleCreateTest());  
  8.         zk3.addAuthInfo("digest", "test:false".getBytes());  
  9.         zk3.getData("/zk-test-auth", false, null);  

zk2設定了正確的許可權 所以可以獲取到節點資料  zk3則會拋異常

 

 org.apache.zookeeper.KeeperException$NoAuthException: KeeperErrorCode = NoAuth for /zk-test-auth

相關文章