Zookeeper中的watcher事件;watcher事件分类;没有注册watcher为什么会触发None事件

首先,下面的表格是所有事件类型和触发条件,大体分为两类,一是连接状态事件(EventType=None),二是节点事件

Zookeeper中的watcher事件;watcher事件分类;没有注册watcher为什么会触发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事件!

可以看到,客户端与服务端成功建立会话触发了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处理的事件分为两类

一是连接状态事件,无需注册,一旦发生就会触发

二是节点事件,需要注册才能触发,且一次注册只能触发一次。