Zookeeper監聽器
- 2019 年 11 月 1 日
- 筆記
Zookeeper提供了分散式數據的發布/訂閱功能,可以讓客戶端訂閱某個Znode,當Znode發生變化時,可以通知所有的訂閱者。這個實現機制在Zookeeper裡面就是Watcher機制。
Watcher機制本質就是客戶端在服務端註冊事件監聽器,當服務端變化時,通知客戶端。
通常Zookeeper客戶端向服務端註冊的監聽器分為兩種:
1、監聽節點數據的變化;
2、監聽子節點數量的變化;
對於監聽器的實現來說,Zookeeper使用監聽器事件來對應不同的監聽器處理,包括:
- NodeCreated(節點創建)
- NodeDeleted(節點刪除)
- NodeDataChanged(節點數據修改)
- NodeChildrenChanged(子節點修改)
除了事件狀態,還包括對應的客戶端連接的狀態:
- Disconneced(連接失敗)
- KeeperState:SyncConnected(連接成功)
- KeeperState:AuthFailed(認證失敗)
- KeeperState:Expired(會話過期)
監聽器工作流程:
1、客戶端註冊:
客戶端通過getData、getChild、exist方法,向Zookeeper註冊,然後將註冊資訊,保存到客戶端的ZKWatchManager中。然後,將數據封裝成Packet,通過ClientCnxn的SendThread將數據發送到服務端;
服務端會將註冊資訊存儲在WatchManager中。
2、服務端通知:
當服務端發生變化時,會封裝一個WatchEvent包括:通知狀態、事件類型(也就是客戶端連接狀態)、節點路徑,通過ServerCnxn發送給客戶端,客戶端ClientCnxn的EventThread會將通知存儲到阻塞隊列中,並移除客戶端的存儲,也就是ZKWatchManager中的數據。
3、客戶端回調:
客戶端ClientCnxn的EventThread會從阻塞隊列中取出監聽通知事件,調用對應的Watcher的process方法,完成客戶端回調處理邏輯。

另外,Zookeeper監聽器有幾個特點:
一次性註冊,也就是一旦一個Watcher被觸發,Zookeeper就會移除響應的監聽,所以,開發人員需要對監聽的節點進行循環註冊。但,循環註冊適用於服務端的變化不頻繁的場景,如果服務端的節點存在頻繁的變化的情況,可能會存在監聽丟失的情況。所以,需要做一些改變,使用監聽器加主動獲取數據相結合的方式,即,註冊監聽器之前主動獲取服務端數據;觸發監聽之後,再主動獲取服務端數據。
輕量級,服務端通知客戶端的最小單位是WatchEvent,只包括通知狀態、事件類型和節點路徑,客戶端向服務端註冊也是盡量減小數據單元,這樣設計的數據量和一次性的註冊,使Zookeeper的記憶體和網路的開銷都很小。