1. 程式人生 > >通過java程式碼使用zookeeper

通過java程式碼使用zookeeper

Zookeeper的使用主要是通過建立其jar包下的Zookeeper例項,並且呼叫其介面方法進行的,主要的操作就是對znode的增刪改操作,監聽znode的變化以及處理。

以下為主要的API使用和解釋

/建立一個Zookeeper例項,第一個引數為目標伺服器地址和埠,第二個引數為Session超時時間,第三個為節點變化時的回撥方法
ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", 500000,new Watcher() {
           // 監控所有被觸發的事件
             public void process(WatchedEvent event) {
           //dosomething
           }
      });
//建立一個節點root,資料是mydata,不進行ACL許可權控制,節點為永久性的(即客戶端shutdown了也不會消失)
zk.create("/root", "mydata".getBytes(),Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

//在root下面建立一個childone znode,資料為childone,不進行ACL許可權控制,節點為永久性的
zk.create("/root/childone","childone".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);

//取得/root節點下的子節點名稱,返回List<String>
zk.getChildren("/root",true);

//取得/root/childone節點下的資料,返回byte[]
zk.getData("/root/childone", true, null);

//修改節點/root/childone下的資料,第三個引數為版本,如果是-1,那會無視被修改的資料版本,直接改掉
zk.setData("/root/childone","childonemodify".getBytes(), -1);

//刪除/root/childone這個節點,第二個引數為版本,-1的話直接刪除,無視版本
zk.delete("/root/childone", -1);
      
//關閉session
zk.close();

Zookeeper的主流應用場景實現思路(除去官方示例) 

(1)
配置管理
集中式的配置管理在應用叢集中是非常常見的,一般商業公司內部都會實現一套集中的配置管理中心,應對不同的應用叢集對於共享各自配置的需求,並且在配置變更時能夠通知到叢集中的每一個機器。

Zookeeper
很容易實現這種集中式的配置管理,比如將APP1的所有配置配置到/APP1 znode下,APP1所有機器一啟動就對/APP1這個節點進行監控(zk.exist("/APP1",true)),並且實現回撥方法Watcher,那麼在zookeeper/APP1 znode節點下資料發生變化的時候,每個機器都會收到通知,Watcher
方法將會被執行,那麼應用再取下資料即可(zk.getData("/APP1",false,null));

以上這個例子只是簡單的粗顆粒度配置監控,細顆粒度的資料可以進行分層級監控,這一切都是可以設計和控制的。

(2)叢集管理 
應用叢集中,我們常常需要讓每一個機器知道叢集中(或依賴的其他某一個叢集)哪些機器是活著的,並且在叢集機器因為宕機,網路斷鏈等原因能夠不在人工介入的情況下迅速通知到每一個機器。

Zookeeper
同樣很容易實現這個功能,比如我在zookeeper伺服器端有一個znode/APP1SERVERS,那麼叢集中每一個機器啟動的時候都去這個節點下建立一個EPHEMERAL型別的節點,比如
server1建立/APP1SERVERS/SERVER1(可以使用ip,保證不重複)server2建立/APP1SERVERS/SERVER2,然後SERVER1SERVER2watch /APP1SERVERS這個父節點,那麼也就是這個父節點下資料或者子節點變化都會通知對該節點進行watch的客戶端。因為EPHEMERAL型別節點有一個很重要的特性,就是客戶端和伺服器端連線斷掉或者session過期就會使節點消失,那麼在某一個機器掛掉或者斷鏈的時候,其對應的節點就會消失,然後叢集中所有對/APP1SERVERS進行watch的客戶端都會收到通知,然後取得最新列表即可。

另外有一個應用場景就是叢集選
master,一旦master掛掉能夠馬上能從slave中選出一個master,實現步驟和前者一樣,只是機器在啟動的時候在APP1SERVERS建立的節點型別變為EPHEMERAL_SEQUENTIAL型別,這樣每個節點會自動被編號,例如

zk.create("/testRootPath/testChildPath1","1".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
        
zk.create("/testRootPath/testChildPath2","2".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
        
zk.create("/testRootPath/testChildPath3","3".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
        
// 建立一個子目錄節點
zk.create("/testRootPath/testChildPath4","4".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);

System.out.println(zk.getChildren("/testRootPath", false));

列印結果:[testChildPath10000000000, testChildPath20000000001, testChildPath40000000003, testChildPath30000000002]
zk.create("/testRootPath", "testRootData".getBytes(),Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

// 建立一個子目錄節點
zk.create("/testRootPath/testChildPath1","1".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);
        
zk.create("/testRootPath/testChildPath2","2".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);
        
zk.create("/testRootPath/testChildPath3","3".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);
        
// 建立一個子目錄節點
zk.create("/testRootPath/testChildPath4","4".getBytes(), Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL);

System.out.println(zk.getChildren("/testRootPath", false));

列印結果:[testChildPath2, testChildPath1, testChildPath4, testChildPath3]

我們預設規定編號最小的為
master,所以當我們對/APP1SERVERS節點做監控的時候,得到伺服器列表,只要所有叢集機器邏輯認為最小編號節點為master,那麼master就被選出,而這個master宕機的時候,相應的znode會消失,然後新的伺服器列表就被推送到客戶端,然後每個節點邏輯認為最小編號節點為master,這樣就做到動態master選舉。