Zookeeper watcher 事件機制原理剖析

amadan發表於2021-09-09

zookeeper 的 watcher 機制,可以分為四個過程:

  • 客戶端註冊 watcher。

  • 服務端處理 watcher。

  • 服務端觸發 watcher 事件。

  • 客戶端回撥 watcher。

其中客戶端註冊 watcher 有三種方式,呼叫客戶端 API 可以分別透過 getData、exists、getChildren 實現,利用前面章節建立的 maven 工程,新建 WatcherDemo 類,以 exists 方法舉例說明其原理。

例項

public class WatcherDemo implements Watcher {
    static ZooKeeper zooKeeper;
    static {
        try {
            zooKeeper = new ZooKeeper("192.168.3.39:2181", 4000,new WatcherDemo());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void process(WatchedEvent event) {
        System.out.println("eventType:"+event.getType());
        if(event.getType()==Event.EventType.NodeDataChanged){
            try {
                zooKeeper.exists(event.getPath(),true);
            } catch (KeeperException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
        String path="/watcher";
        if(zooKeeper.exists(path,false)==null) {
            zooKeeper.create("/watcher", "0".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }
        Thread.sleep(1000);
        System.out.println("-----------");
        //true表示使用zookeeper例項中配置的watcher
        Stat stat=zooKeeper.exists(path,true);
        System.in.read();
    }
}

執行完程式,控制檯顯示:

圖片描述

此時啟動 zookeeper 命令列終端,檢視並且刪除 watcher 節點:

圖片描述

IDE 控制檯輸出,觸發了節點刪除事件:

圖片描述

客戶端傳送請求給服務端是透過 TCP 長連線建立網路通道,底層預設是透過 java 的 NIO 方式,也可以配置 netty 實現方式。

圖片描述

註冊 watcher 監聽事件流程圖:

圖片描述

1、客戶端傳送事件通知請求

在 Zookeeper 類呼叫 exists 方法時候,把建立事件監聽封裝到 request 物件中,watch 屬性設定為 true,待服務端返回 response 後把監聽事件封裝到客戶端的 ZKWatchManager 類中。

圖片描述

2、服務端處理 watcher 事件的請求

服務端 NIOServerCnxn 類用來處理客戶端傳送過來的請求,最終呼叫到 FinalRequestProcessor,其中有一段原始碼新增客戶端傳送過來的 watcher 事件:

圖片描述

然後進入 statNode 方法,在 DataTree 類方法中新增 watcher 事件,並儲存至 WatchManager 的 watchTable 與 watchTable 中。

圖片描述

圖片描述

3、服務端觸發 watcher 事件流程:

若服務端某個被監聽的節點發生事務請求,服務端處理請求過程中呼叫 FinalRequestProcessor 類 processRequest 方法中的程式碼如下所示:

圖片描述

刪除呼叫鏈最終到 DataTree 類中刪除節點分支的觸發程式碼段:

圖片描述

進入 WatchManager 類的 triggerWatch 方法:

圖片描述

繼續跟蹤進入 NIOServerCnxn,構建了一個 xid 為 -1,zxid 為 -1 的 ReplyHeader 物件,然後再呼叫 sendResonpe 方法。

圖片描述

4、客戶端回撥 watcher 事件

客戶端 SendThread 類 readResponse 方法接收服務端觸發的事件通知,進入 xid 為 -1 流程,處理 Event 事件。

圖片描述

圖片描述

作者公眾號:一起寫程式

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2310/viewspace-2797753/,如需轉載,請註明出處,否則將追究法律責任。

相關文章