Zookeeper深入原理(2) - Watcher 監(jiān)聽機制

1.Zookeeper Watcher(監(jiān)聽機制)

Zookeeper 提供了分布式 數(shù)據(jù)發(fā)布和訂閱功能,一個典型的發(fā)布和訂閱模型系統(tǒng)定義了一種一對多的訂閱關系,能讓多個訂閱者同時監(jiān)聽某一個主題的對象,當這個主題對象自身狀態(tài)變化時,會通知所有訂閱者,使它們能夠做出相應的處理。

Zookeeper中引入了Watcher機制來實現(xiàn)這種分布式通知的功能。Zookeeper允許客戶端向服務端注冊一個Watcher監(jiān)聽。當服務端的一些事件出發(fā)了Watcher監(jiān)聽機制,就會向指定得客戶端發(fā)送一個事件通知來實現(xiàn)分布式的通知功能。

觸發(fā)事件種類: 節(jié)點創(chuàng)建、節(jié)點刪除、節(jié)點改變、子節(jié)點改變等。

總的來說可以概括Watcher分為以下三個過程: 客戶端向服務端注冊Watcher、服務端事件觸發(fā)Watcher、客戶端回調(diào)Watcher得到觸發(fā)事件情況。????

2.Watch機制特點

一次性觸發(fā)

事件觸發(fā)監(jiān)聽,一個Watcher Event 就會被發(fā)送到設置監(jiān)聽的客戶端,這種效果是一次性的,后續(xù)再發(fā)生同樣的事件,不會觸發(fā)機制。

事件封裝

Zookeeper使用WatchedEvent對象來封裝服務端事件并傳遞。

WatchedEvent包含每一個事件的三個基本屬性:

通知狀態(tài)(keeperState) 、事件類型(EventType)、節(jié)點路徑(path)

Event 異步發(fā)送

Watcher的通知事件是從服務端異步發(fā)送到客戶端的。

先注冊再觸發(fā)

Zookeeper的Watch機制,必須客戶端在服務端注冊監(jiān)聽,服務器端觸發(fā)監(jiān)聽機制,才會通知客戶端。

3.通知狀態(tài)和事件類型

同一個事件類型在不同的通知狀態(tài)中代表的含義有所不同,下表列舉了常見的通知狀態(tài)和事件類型。

事件封裝:Watcher得到的事件是被封裝過的, 包括三個內(nèi)容keeperState, eventType, path


其中連接狀態(tài)事件(type=None, path=null)不需要客戶端注冊,客戶端只要有需要直接處理就行了。

4.Shell 客戶端設置Watcher

設置節(jié)點數(shù)據(jù)變動監(jiān)聽:

設置監(jiān)聽

通過另一個客戶端更改節(jié)點數(shù)據(jù):

更改數(shù)據(jù)

此時設置監(jiān)聽的節(jié)點收到通知:

收到通知

5.ZooKeeperJava?API操作

這里操作Zookeeper的JavaAPI使用的是一套zookeeper客戶端框架 Curator ,解決了很多Zookeeper客戶端非常底層的細節(jié)開發(fā)工作 。

Curator包含了幾個包:

curator-framework:對zookeeper的底層api的一些封裝

curator-recipes:封裝了一些高級特性,如:Cache事件監(jiān)聽、選舉、分布式鎖、分布式計數(shù)器等

Maven依賴(使用curator的版本:2.12.0,對應Zookeeper的版本為:3.4.x,如果跨版本會有兼容性問題,很有可能導致節(jié)點操作失敗):

? ? 1.引入maven坐標

<dependencies>

????????<dependency>

????????????<groupId>org.apache.curator</groupId>

????????????<artifactId>curator-framework</artifactId>

????????????<version>2.12.0</version>

????????</dependency>


????????<dependency>

????????????<groupId>org.apache.curator</groupId>

????????????<artifactId>curator-recipes</artifactId>

????????????<version>2.12.0</version>

????????</dependency>


????????<dependency>

????????????<groupId>com.google.collections</groupId>

????????????<artifactId>google-collections</artifactId>

????????????<version>1.0</version>

????????</dependency>

????????<dependency>

????????????<groupId>junit</groupId>

????????????<artifactId>junit</artifactId>

????????????<version>RELEASE</version>

????????</dependency>

????????<dependency>

????????????<groupId>org.slf4j</groupId>

????????????<artifactId>slf4j-simple</artifactId>

????????????<version>1.7.25</version>

????????</dependency>

????</dependencies>


????<build>

????????<plugins>

????????????<!--java編譯插件 -->

????????????<plugin>

????????????????<groupId>org.apache.maven.plugins</groupId>

????????????????<artifactId>maven-compiler-plugin</artifactId>

????????????????<version>3.2</version>

????????????????<configuration>

????????????????????<source>1.8</source>

????????????????????<target>1.8</target>

????????????????????<encoding>UTF-8</encoding>

????????????????</configuration>

????????????</plugin>

????????</plugins>

???</build>

2.節(jié)點的操作

/*

?創(chuàng)建節(jié)點

?*/

@Test

public?void?createZnode()?throws?Exception {

//1:定制一個重試策略

/*

param1: 重試的間隔時間

param2:重試的最大次數(shù)

?*/

RetryPolicy retryPolicy =?new?ExponentialBackoffRetry(1000,1);

//2:獲取一個客戶端對象

/*

???param1:要連接的Zookeeper服務器列表

???param2:會話的超時時間

???param3:鏈接超時時間

???param4:重試策略

?*/

String connectionStr =?"192.168.88.161:2181,192.168.88.162:2181,192.168.88.163:2181";

CuratorFramework client =?CuratorFrameworkFactory.newClient(connectionStr,?8000,?8000,?retryPolicy);


//3:開啟客戶端

client.start();

//4:創(chuàng)建節(jié)點

/*

??節(jié)點類型:

???CreateMode.PERSISTENT:永久節(jié)點

???CreateMode.PERSISTENT_SEQUENTIAL:永久序列化節(jié)點

???CreateMode.EPHEMERAL:臨時節(jié)點

???CreateMode.EPHEMERAL_SEQUENTIAL:臨時序列化節(jié)點

???/hello2 :節(jié)點路徑

???world :節(jié)點數(shù)據(jù)

?*/

client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/hello2","world".getBytes());

//5:關閉客戶端

client.close();

}

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯(lián)系作者。

推薦閱讀更多精彩內(nèi)容