1. 程式人生 > 其它 >Zookeeper中watcher觸發none事件的原因

Zookeeper中watcher觸發none事件的原因

Zookeeper中watcher觸發none事件的原因

首先,下面的表格是所有事件型別和觸發條件,大體分為兩類,一是連線狀態事件(EventType=None),二是節點事件

然後直接看程式碼

public class zkClient {

    private String connectString="hadoop102:2181,hadoop103:2181,hadoop104:2181";
    private int sessionTimeout=100000;
    private ZooKeeper zkClient = null;

    @Before
    public void init() throws IOException {

        zkClient 
= new ZooKeeper(connectString, sessionTimeout, new Watcher() { public void process(WatchedEvent watchedEvent) { if ( watchedEvent.getType() == null || "".equals( watchedEvent.getType())) { return; } System.out.println("已經觸發了" + watchedEvent.getType() + "事件!"); } }); }
@Test public void getChildren() throws KeeperException, InterruptedException { //List<String> children = zkClient.getChildren("/", true);
    Thread.sleep(Long.MAX_VALUE); } }

這裡我們執行getChildren(),由於@Before會先執行init()連線服務端,然後直接進入睡眠狀態。

執行結果:

 已經觸發了None事件!

可以看到,即使沒有註冊watcher,同樣觸發了連線狀態事件

接下來我們加入getChildren()函式進行watcher註冊

package com.weng.zk;

import org.apache.zookeeper.*;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class zkClient {


    private String connectString="hadoop102:2181,hadoop103:2181,hadoop104:2181";
    private int sessionTimeout=100000;
    private ZooKeeper zkClient = null;


    @Before
    public void init() throws IOException {

        zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                if ( watchedEvent.getType() == null || "".equals( watchedEvent.getType())) {
                    return;
                }
                System.out.println("已經觸發了" +  watchedEvent.getType() + "事件!");
            }
        });

    }


    @Test
    public void getChildren() throws KeeperException, InterruptedException {
        List<String> children = zkClient.getChildren("/", true);
        Thread.sleep(Long.MAX_VALUE);
    }
}

執行結果:

已經觸發了None事件!

然後我們在另一臺客戶端刪除一個子節點

已經觸發了NodeChildrenChanged事件!

再刪除一個子節點,控制檯沒有再列印。

為什麼有且只打印了兩次呢?

第一次列印的是連線狀態事件(EventType=None)一旦發生就會觸發watcher,不需要註冊

第二次列印的是節點事件,由於我們在另一臺客戶端刪除一個子節點,觸發了該事件。

但節點事件具有一次性,一旦被觸發就會被移除。所有再刪除一個子節點也不會繼續列印。

結論:

watcher處理的事件分為兩類

一是連線狀態事件,該事件一旦發生就會觸發watcher,不需要註冊

二是節點事件,具有一次性,一旦被觸發就會被移除。