轉載自: http://www.cnblogs.com/sunddenly/p/4031881.html
1.API
?
2.API 示例
ZooKeeper中的組成員關系
理解ZooKeeper的一種方法就是將其看作一個具有高可用性的文件系統。但這個文件系統中沒有文件和目錄,而是統一使用“節點”(node)的概念,稱為znode。znode既可以作為保存數據的容器(如同文件),也可以作為保存其他znode的容器(如同目錄)。所有的znode構成一個層次化的命名空間。一種自然的建立組成員列表的方式就是利用這種層次結構,創建一個以組名為節點名的znode作為父節點,然后以組成員名(服務器名)為節點名來創建作為子節點的znode。如下圖給出了一組具有層次結構的znode。
?
創建組示例代碼:
package org.zk;import java.io.IOException; import java.util.concurrent.CountDownLatch;import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper;public class CreateGroup implements{private static final int SESSION_TIMEOUT=5000;private ZooKeeper zk;private CountDownLatch connectedSignal=new CountDownLatch(1);@Overridepublic void(WatchedEvent event) {if(event.getState()==KeeperState.SyncConnected){connectedSignal.countDown();}}public static void main(String[] args) throws IOException, InterruptedException, KeeperException {CreateGroup createGroup = new CreateGroup();createGroup.connect(args[0]);createGroup.create(args[1]);createGroup.close();}private void close() throws InterruptedException {zk.close();}private void create(String groupName) throws KeeperException, InterruptedException {String path="/"+groupName;if(zk.exists(path, false)== null){}System.out.println("Created:"+path);} private void connect(String hosts) throws IOException, InterruptedException {zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this);connectedSignal.await();} }
?
代碼分析
在上面代碼中,main()方法執行時,創建了一個CreateGroup的實例并且調用了這個實例的connect()方法。connect方法實例化了一個新的ZooKeeper類的對象,這個類是客戶端API中的主要類,并且負責維護客戶端和ZooKeeper服務之間的連接。ZooKeeper類的構造函數有三個參數:
第一個是:ZooKeeper服務的主機地址,可指定端口,默認端口是2181。
第二個是:以毫秒為單位的會話超時參數,這里我們設成5秒。
第三個是:參數是一個Watcher對象的實例。
?
Watcher對象接收來自于ZooKeeper的回調,以獲得各種事件的通知。在這個例子中,CreateGroup是一個Watcher對象,因此我們將它傳遞給ZooKeeper的構造函數。
當一個ZooKeeper的實例被創建時,會啟動一個線程連接到ZooKeeper服務。由于對構造函數的調用是立即返回的,因此在使用新建的ZooKeeper對象之前一定要等待其與ZooKeeper服務之間的連接建立成功。我們使用Java的CountDownLatch類來阻止使用新建的ZooKeeper對象,直到這個ZooKeeper對象已經準備就緒。這就是Watcher類的
用途,在它的接口中只有一個方法:
public void process(WatcherEvent event);
客戶端已經與ZooKeeper建立連接后,Watcher的process()方法會被調用,參數是一個表示該連接的事件。在接收到一個連接事件(由 Watcher.Event.KeeperState的枚舉型值SyncConnected來表示)時,我們通過調用CountDownLatch的countDown()方法來遞減它的計數器。鎖存器(latch)被創建時帶有一個值為1的計數器,用于表示在它釋放所有等待線程之前需要發生的事件數。在調用一歡countDown()方法之后,計數器的值變為0,則await()方法返回。
現在connect()方法已經返回,下一個執行的是CreateGroup的create()方法。在這個方法中,我們使用ZooKeeper實例中的create()方法來創建一個新的ZooKeeper的znode。所需的參數包括:
路徑:用字符串表示。
znode的內容:字節數組,本例中使用空值。
訪問控制列表:簡稱ACL,本例中使用了完全開放的ACL,允許任何客戶端對znode進行讀寫。
創建znode的類型:有兩種類型的znode:短暫的和持久的。
創建znode的客戶端斷開連接時,無論客戶端是明確斷開還是因為任何原因而終止,短暫znode都會被ZooKeeper服務刪除。與之相反,當客戶端斷開連接時,持久znode不會被刪除。我們希望代表一個組的znode存活的時間應當比創建程序的生命周期要長,因此在本例中我們創建了一個持久的znode。
create()方法的返回值是ZooKeeper所創建的路徑,我們用這個返回值來打印一條表示路徑成功創建的消息。當我們查看“順序znode”(sequential znode)時.會發現create()方法返回的路徑與傳遞給該方法的路徑不同。
?
加入組
package org.zk;import java.io.IOException;import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooDefs.Ids;public class JoinGroup extends ConnectionWatcher{public void join(String groupName,String memberName) throws KeeperException, InterruptedException{;String createdPath=zk.(path, null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);System.out.println("Created:"+createdPath);}public static void main(String[] args) throws InterruptedException, IOException, KeeperException {JoinGroup joinGroup = new JoinGroup();joinGroup.connect(args[0]);joinGroup.join(args[1], args[2]);//stay alive until process is killed or thread is interrupted Thread.sleep(Long.MAX_VALUE);} }
列出組成員
package org.zk;import java.io.IOException; import java.util.List;import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooKeeper;public class ListGroup extends ConnectionWatcher {public void list(String groupNmae) throws KeeperException, InterruptedException{String path ="/"+groupNmae;try {List<String> children = (path, false);if(children.isEmpty()){System.out.printf("No memebers in group %s\n",groupNmae);System.exit(1);}for(){System.out.println(child);}} catch (KeeperException.NoNodeException e) {System.out.printf("Group %s does not exist \n", groupNmae);System.exit(1);} }public static void main(String[] args) throws IOException, InterruptedException, KeeperException {ListGroup listGroup = new ListGroup();listGroup.connect(args[0]);listGroup.list(args[1]);listGroup.close();} }
刪除組
下面來看如何刪除一個組。ZooKeeper類提供了一個delete()方法,該方法有兩個參數:
1. 路徑
2. 版本號
如果所提供的版本號與znode的版本號一致,ZooKeeper會刪除這個znode。這是一種樂觀的加鎖機制,使客戶端能夠檢測出對znode的修改沖突。通過將版本號設置為-1,可以繞過這個版本檢測機制,不管znode的版本號是什么而直接將其刪除。ZooKeeper不支持遞歸的刪除操作,因此在刪除父節點之前必須先刪除子節點。
在代碼3.5中,DeleteGroup類用于刪除一個組及其所有成員。
代碼3.5用于刪除一個組及其所有成員的程序
package org.zk;import java.io.IOException; import java.util.List;import org.apache.zookeeper.KeeperException;public class DeleteGroup extends ConnectionWatcher{public void delete(String groupName) throws InterruptedException, KeeperException{String path="/"+groupName;List<String> children;try {children = (path, false);for(String child:children){ }zk.delete(path, -1);} catch (KeeperException.NoNodeException e) {System.out.printf("Group %s does not exist\n", groupName);System.exit(1);} }public static void main(String[] args) throws InterruptedException, IOException, KeeperException {DeleteGroup deleteGroup = new DeleteGroup();deleteGroup.connect(args[0]);deleteGroup.delete(args[1]);deleteGroup.close();} }