Zookeeper的監聽機制api與原理
阿新 • • 發佈:2018-11-24
1.連線Zookeeper,註冊監聽
ZooKeeper zkCli = new ZooKeeper("192.168.50.183:2181,192.168.50.184:2181,192.168.50.185:2181", 3000, new Watcher() {
//監聽回撥
@Override
public void process(WatchedEvent event) {
System.out.println("正在監聽中.....");
}
});
2.註冊監聽getChilren
通過zkCli.getchildren("/",new watch()){}來註冊監聽,監聽的是整個根節點,但是這個監聽只能監聽一次。
執行緒休眠是為了讓監聽等待事件發生,不然會隨著程式直接執行完。
public class WatchDemo1 { static List<String> children = null; public static void main(String[] args) throws IOException, KeeperException, InterruptedException { ZooKeeper zkCli = new ZooKeeper("192.168.50.183:2181,192.168.50.184:2181,192.168.50.185:2181", 3000, new Watcher() { //監聽回撥 @Override public void process(WatchedEvent event) { System.out.println("正在監聽中....."); } }); //監聽目錄 children = zkCli.getChildren("/", new Watcher() { @Override public void process(WatchedEvent event) { System.out.println("監聽路徑為:" + event.getPath()); System.out.println("監聽的型別為:" + event.getType()); System.out.println("資料被2貨修改了!!!"); for(String c:children) { System.out.println(c); } } }); Thread.sleep(Long.MAX_VALUE); } }
可以通過修改zk客戶端的/節點下的子節點,getchilren會返回列表(/下的子節點資訊)
3.註冊監聽getData
getData監聽的為一個節點
同樣只監聽一次,返回的是該節點的內容
public class WatchDemo { public static void main(String[] args) throws IOException, KeeperException, InterruptedException { ZooKeeper zkCli = new ZooKeeper("192.168.50.183:2181,192.168.50.184:2181,192.168.50.185:2181", 3000, new Watcher() { //監聽回撥 @Override public void process(WatchedEvent event) { } }); byte[] data = zkCli.getData("/hunter", new Watcher() { //監聽的具體內容 @Override public void process(WatchedEvent event) { System.out.println("監聽路徑為:" + event.getPath()); System.out.println("監聽的型別為:" + event.getType()); System.out.println("資料被2貨修改了!!!"); } }, null); System.out.println(new String(data)); Thread.sleep(Long.MAX_VALUE); } }
4.永久監聽
public class ZkClient {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
//1.獲取連線
ZkClient zkClient = new ZkClient();
zkClient.getConnect();
//2.監聽服務的節點資訊
zkClient.getServers();;
//3.業務邏輯(一直監聽)
zkClient.getWatch();
}
//3.業務邏輯
public void getWatch() throws InterruptedException {
Thread.sleep(Long.MAX_VALUE);
}
//2.監聽服務的節點資訊
public void getServers() throws KeeperException, InterruptedException {
List<String> children = zkCli.getChildren("/servers", true);
ArrayList<String> serverList = new ArrayList<String>();
//獲取每個節點的資料
for(String c:children) {
byte[] data = zkCli.getData("/servers/" + c, true, null);
serverList.add(new String(data));
}
//列印伺服器列表
System.out.println(serverList);
}
private String connectString = "192.168.232.132:2181,192.168.232.133:2181,192.168.232.134:2181";
private int sessionTimeout = 3000;
ZooKeeper zkCli;
//1.連線叢集
public void getConnect() throws IOException {
zkCli = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
@Override
public void process(WatchedEvent event) {
List<String> children;
try {
//監聽父節點
children = zkCli.getChildren("/servers", true);
//建立集合儲存伺服器列表
ArrayList<String> serverList = new ArrayList<String>();
//獲取每個節點的資料
for(String c:children) {
byte[] data = zkCli.getData("/servers/" + c, true, null);
serverList.add(new String(data));
}
//列印伺服器列表
System.out.println(serverList);
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
服務端上下線機器,客戶端都能動態感知,這裡是先通過getchilren獲得根節點下的子節點資訊列表,然後通過getData來獲得每個子節點的內容,並傳給ArrayList,最後通過輸出ArrayList來獲得當前線上的機器
5.總結
1.從1-3的程式碼可以看出,zookeeper註冊的監聽是一次的,如果你還需要監聽第二次,那麼就要重新註冊。
那我們永久監聽是怎麼做到的呢?
2.可以看到在我們連線zookeeper的時候,註冊了監聽,然後在process方法中,我們的getChildren,getData的第二個引數為true,這裡是使用預設的監聽,我的理解是會回撥到我們連線zookeeper的時候註冊監聽的process方法,那因為我們的getChildren,getData是放在這個方法裡的,每次發生一個事件,然後就一直重複這樣的行為,達到永久監聽的效果。
3.這裡我們可以測試下,getChildren,getData不放在process當中,並且引數為true,那我的測試結果為,監聽了一次,監聽完了後,又返回連線zk時的process方法中的語句.這裡就證明了我的理解應該是對了。