Zookeeper之事件监听机制

目录

一、watcher概念

二、watcher架构

三、watcher特性

四、watcher接口设计

五、watcher监控之检查节点是否存在

六、watcher监控之查看节点

七、watcher监控之查看子节点

八、总结


一、watcher概念

Zookeeper提供了数据的发布/订阅功能,多个订阅者可同时监听某一特定主题对象,当该主题对象的自身状态发生变化时(例如节点内容改变、节点下的子节点列表改变等),会实时、主动通知所有订阅者。

Zookeeper采用了Watcher机制实现数据的发布/订阅功能。该机制在被订阅对象发生变化时会异步通知客户端,因此客户端不必在Watcher注册后轮询阻塞,从而减轻了客户端压力。

二、watcher架构

Watcher实现由三个部分组成:

  • Zookeeper服务端
  • Zookeeper客户端
  • 客户端的WatchManager对象

客户端首先将Watcher注册到服务端,同时将Watcher对象保存到客户端的Watch管理器中。当ZooKeeper服务端监听的数据状态发生变化时,服务端会主动通知客户端,接着客户端的Watch管理器会触发相关Watcher来回调相应处理逻辑,从而完成整体的数据发布/订阅流程。

三、watcher特性

  • 一次性:watcher是一次性的,一旦被触发就会移除,再次使用时需要重新注册;
  • 客户端顺序回调:watcher回调是顺序串行化执行的,只有回调后客户端才能看到最新的数据状态。一个watcher回调逻辑不应该太多,以免影响别的watcher执行;
  • 轻量级:WatchEvent是最小的通信单元,结构上只包含通知状态、事件类型和节点路径,并不会告诉数据节点变化前后的具体内容;
  • 时效性:watcher只有在当前session彻底失效时才会无效,若在session有效期内快速重连成功,则watcher依然存在,仍可接收到通知;

四、watcher接口设计

Watcher是一个接口,任何实现了Watcher接口的类就是一个新的Watcher。Watcher内部包含了两个枚举类:KeeperState、EventType。

  • Watcher通知状态(KeeperState)

KeeperState是客户端与服务端连接状态发生变化时对应的通知类型,是一个枚举类,其枚举属性如下:

/** @deprecated */
@Deprecated
Unknown(-1),
Disconnected(0),              #客户端与服务器断开连接时
/** @deprecated */
@Deprecated
NoSyncConnected(1),
SyncConnected(3),             #客户端与服务器正常连接时
AuthFailed(4),                #身份认证失败时 
ConnectedReadOnly(5),
SaslAuthenticated(6),
Expired(-112);               #会话session失效时
  • Watcher事件类型(EventType)

EventType是数据节点(znode)发生变化时对应的通知类型。EventType变化时,KeeperState永远处于SyncConnected通知状态下;当KeeperState发生变化时,EventType永远为None。EventType是一个枚举类,枚举属性如下:

None(-1),                    #无
NodeCreated(1),              #Watcher监听的数据节点被创建时
NodeDeleted(2),              #Watcher监听的数据节点被删除时
NodeDataChanged(3),          #Watcher监听的数据节点内容发生变更时
NodeChildrenChanged(4);      #Watcher监听的数据节点的子节点列表发生变更时

注:客户端接收到的相关事件通知中只包含状态及类型等信息,不包括节点变化前后的具体内容,变化前的数据需业务自身存储,变化后的数据需调用get等方法重新获取;

五、watcher监控之检查节点是否存在

案例:

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

public class ZookeeperWatcherExists {

    private static final String ZOOKEEPER_SERVER_ADDRESS = "192.168.179.133:2181";
    private static final Logger logger = LoggerFactory.getLogger(ZookeeperWatcherExists.class);
    private static ZooKeeper zooKeeper = null;

    static {
        try {
            zooKeeper = new ZooKeeper(ZOOKEEPER_SERVER_ADDRESS, 3000, new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    // 连接成功
                    if (event.getState() == Event.KeeperState.SyncConnected) {
                        logger.info("连接服务端成功...");
                    }
                    logger.info("节点路径:" + event.getPath());
                    logger.info("事件类型:" + event.getType());
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 1. 使用连接对象中的watcher
     *
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void watcherExists01() throws KeeperException, InterruptedException {
        zooKeeper.exists("/watcher1", true);
        Thread.sleep(50000);
    }

    /**
     * 2. 自定义watcher对象
     *
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void watcherExists02() throws KeeperException, InterruptedException {
        zooKeeper.exists("/watcher1", new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                logger.info("节点路径:" + event.getPath());
                logger.info("事件类型:" + event.getType());
            }
        });
        Thread.sleep(50000);
    }

    /**
     * 3. watcher重复监听
     *
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void watcherExists03() throws KeeperException, InterruptedException {
        Watcher watcher = new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                try {
                    logger.info("节点路径:" + event.getPath());
                    logger.info("事件类型:" + event.getType());
                    zooKeeper.exists("/watcher1", this);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        };
        zooKeeper.exists("/watcher1", watcher);
        Thread.sleep(50000);
    }

    /**
     * 4. 同时注册多个watcher监听
     *
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void watcherExists04() throws KeeperException, InterruptedException {
        // 注册多个监听器对象
        zooKeeper.exists("/watcher1", new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                logger.info("节点路径1:" + event.getPath());
                logger.info("事件类型1:" + event.getType());
            }
        });

        zooKeeper.exists("/watcher1", new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                logger.info("节点路径2:" + event.getPath());
                logger.info("事件类型2:" + event.getType());
            }
        });
        Thread.sleep(50000);
    }

    public static void main(String[] args) throws KeeperException, InterruptedException {
        ZookeeperWatcherExists zookeeperWatcherExists = new ZookeeperWatcherExists();
        zookeeperWatcherExists.watcherExists01();
//        zookeeperWatcherExists.watcherExists02();
//        zookeeperWatcherExists.watcherExists03();
//        zookeeperWatcherExists.watcherExists04();
    }

}

 以上是主要代码,下面分四种情况分别进行测试:

【a】使用连接对象中的watcher

首先先使用终端连接上ZK服务器,先创建一个节点:/watcher1,创建完成后对节点数据进行修改、删除操作,然后观察后端监听器日志:

[zk: localhost:2181(CONNECTED) 1] create /watcher1 "watcher1"
Created /watcher1
[zk: localhost:2181(CONNECTED) 2] set /watcher1 "watcher11"
cZxid = 0xb1
ctime = Thu Dec 24 17:20:14 CST 2020
mZxid = 0xb3
mtime = Thu Dec 24 17:22:12 CST 2020
pZxid = 0xb1
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 9
numChildren = 0

后端日志如下,可以看到成功监听到NodeDataChanged节点数据变化事件。

17:22:12.363 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 连接服务端成功...
17:22:12.363 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 节点路径:/watcher1
17:22:12.364 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 事件类型:NodeDataChanged

【b】自定义watcher对象

[zk: localhost:2181(CONNECTED) 13] create /watcher1 "watcher1"
Created /watcher1

后端日志如下,可以看到成功监听到NodeCreated节点数据变化事件,并且监听是一次性的。

17:26:24.189 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 节点路径:/watcher1
17:26:24.189 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 事件类型:NodeCreated

【c】watcher重复监听

[zk: localhost:2181(CONNECTED) 15] create /watcher1 "watcher1"
Created /watcher1
[zk: localhost:2181(CONNECTED) 16] set /watcher1 "watcher11"
cZxid = 0xc6
ctime = Thu Dec 24 17:27:46 CST 2020
mZxid = 0xc7
mtime = Thu Dec 24 17:28:03 CST 2020
pZxid = 0xc6
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 9
numChildren = 0
[zk: localhost:2181(CONNECTED) 17] delete /watcher1

后端日志如下,可以看到成功监听到节点变化事件,并且可以重复监听的。

17:27:46.299 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 节点路径:/watcher1
17:27:46.299 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 事件类型:NodeCreated
17:28:03.524 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 节点路径:/watcher1
17:28:03.524 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 事件类型:NodeDataChanged
17:28:07.539 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 节点路径:/watcher1
17:28:07.539 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 事件类型:NodeDeleted

【d】同时注册多个watcher监听

[zk: localhost:2181(CONNECTED) 18] create /watcher1 "watcher1"
Created /watcher1

后端日志如下,可以看到成功监听到节点变化事件,并且两个监听器都能监听到变化事件。

17:29:57.663 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 节点路径2:/watcher1
17:29:57.663 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 事件类型2:NodeCreated
17:29:57.663 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 节点路径1:/watcher1
17:29:57.663 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherExists - 事件类型1:NodeCreated

六、watcher监控之查看节点

案例:

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

public class ZookeeperWatcherGetData {

    private static final String ZOOKEEPER_SERVER_ADDRESS = "192.168.179.133:2181";
    private static final Logger logger = LoggerFactory.getLogger(ZookeeperWatcherGetData.class);
    private static ZooKeeper zooKeeper = null;

    static {
        try {
            zooKeeper = new ZooKeeper(ZOOKEEPER_SERVER_ADDRESS, 6000, new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    if (event.getState() == Event.KeeperState.SyncConnected) {
                        logger.info("连接服务端成功...");
                    }
                    logger.info("节点路径:" + event.getPath());
                    logger.info("事件类型:" + event.getType());
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 1. 使用连接对象中的watcher
     *
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void watcherGetData1() throws KeeperException, InterruptedException {
        zooKeeper.getData("/watcher2", true, null);
        Thread.sleep(50000);
    }

    /**
     * 2. 自定义watcher对象
     *
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void watcherGetData2() throws KeeperException, InterruptedException {
        zooKeeper.getData("/watcher2", new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                logger.info("节点路径:" + event.getPath());
                logger.info("事件类型:" + event.getType());
            }
        }, null);
        Thread.sleep(50000);
    }

    /**
     * 3. watcher重复监听
     *
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void watcherGetData3() throws KeeperException, InterruptedException {
        Watcher watcher = new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                try {
                    logger.info("节点路径:" + event.getPath());
                    logger.info("事件类型:" + event.getType());
                    if (event.getType() == Event.EventType.NodeDataChanged) {
                        zooKeeper.getData("/watcher2", this, null);
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        };
        zooKeeper.getData("/watcher2", watcher, null);
        Thread.sleep(50000);
    }

    /**
     * 4. 同时注册多个监听器对象
     *
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void watcherGetData4() throws KeeperException, InterruptedException {
        zooKeeper.getData("/watcher2", new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                try {
                    logger.info("节点路径1:" + event.getPath());
                    logger.info("事件类型1:" + event.getType());
                    if (event.getType() == Event.EventType.NodeDataChanged) {
                        zooKeeper.getData("/watcher2", this, null);
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }, null);

        zooKeeper.getData("/watcher2", new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                try {
                    logger.info("节点路径2:" + event.getPath());
                    logger.info("事件类型2:" + event.getType());
                    if (event.getType() == Event.EventType.NodeDataChanged) {
                        zooKeeper.getData("/watcher2", this, null);
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }, null);
        Thread.sleep(50000);
    }

    public static void main(String[] args) throws KeeperException, InterruptedException {
        ZookeeperWatcherGetData zookeeperWatcherGetData = new ZookeeperWatcherGetData();
        zookeeperWatcherGetData.watcherGetData1();
        zookeeperWatcherGetData.watcherGetData2();
        zookeeperWatcherGetData.watcherGetData3();
        zookeeperWatcherGetData.watcherGetData4();
    }
}

以上是主要代码,下面分四种情况分别进行测试:

【a】使用连接对象中的watcher

[zk: localhost:2181(CONNECTED) 20] set /watcher2 "watcher22"
cZxid = 0xcd
ctime = Fri Dec 25 09:51:12 CST 2020
mZxid = 0xcf
mtime = Fri Dec 25 09:51:37 CST 2020
pZxid = 0xcd
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 9
numChildren = 0

后端日志如下,可以看到成功监听到节点变化事件。

09:51:37.281 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 连接服务端成功...
09:51:37.281 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 节点路径:/watcher2
09:51:37.281 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 事件类型:NodeDataChanged

【b】自定义watcher对象

[zk: localhost:2181(CONNECTED) 21] set /watcher2 "watcher22222222"
cZxid = 0xcd
ctime = Fri Dec 25 09:51:12 CST 2020
mZxid = 0xd2
mtime = Fri Dec 25 09:52:15 CST 2020
pZxid = 0xcd
cversion = 0
dataVersion = 2
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 15
numChildren = 0

后端日志如下,可以看到成功监听到节点变化事件。

09:52:15.759 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 节点路径:/watcher2
09:52:15.759 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 事件类型:NodeDataChanged

【c】watcher重复监听

[zk: localhost:2181(CONNECTED) 22] set /watcher2 "watcher2"       
cZxid = 0xcd
ctime = Fri Dec 25 09:51:12 CST 2020
mZxid = 0xd5
mtime = Fri Dec 25 09:52:57 CST 2020
pZxid = 0xcd
cversion = 0
dataVersion = 3
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0
[zk: localhost:2181(CONNECTED) 23] delete /watcher2 

后端日志如下,可以看到成功监听到节点变化事件。

09:52:57.288 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 节点路径:/watcher2
09:52:57.288 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 事件类型:NodeDataChanged

09:53:06.505 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 节点路径:/watcher2
09:53:06.505 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 事件类型:NodeDeleted

【d】同时注册多个监听器对象

[zk: localhost:2181(CONNECTED) 25] set /watcher2 "w2"
cZxid = 0xda
ctime = Fri Dec 25 09:53:57 CST 2020
mZxid = 0xde
mtime = Fri Dec 25 09:55:24 CST 2020
pZxid = 0xda
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 2
numChildren = 0

后端日志如下,可以看到成功监听到节点变化事件。

09:55:24.359 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 节点路径1:/watcher2
09:55:24.359 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 事件类型1:NodeDataChanged

09:55:24.361 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 节点路径2:/watcher2
09:55:24.361 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetData - 事件类型2:NodeDataChanged

七、watcher监控之查看子节点

案例:

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

public class ZookeeperWatcherGetChildren {

    private static final String ZOOKEEPER_SERVER_ADDRESS = "192.168.179.133:2181";
    private static final Logger logger = LoggerFactory.getLogger(ZookeeperWatcherGetChildren.class);
    private static ZooKeeper zooKeeper = null;

    static {
        try {
            zooKeeper = new ZooKeeper(ZOOKEEPER_SERVER_ADDRESS, 6000, new Watcher() {
                @Override
                public void process(WatchedEvent event) {
                    if (event.getState() == Event.KeeperState.SyncConnected) {
                        logger.info("连接服务端成功...");
                    }
                    logger.info("节点路径:" + event.getPath());
                    logger.info("事件类型:" + event.getType());
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 1. 使用连接对象中的watcher
     *
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void watcherGetChildren01() throws KeeperException, InterruptedException {
        zooKeeper.getChildren("/watcher3", true);
        Thread.sleep(50000);
    }

    /**
     * 2. 自定义watcher
     *
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void watcherGetChildren02() throws KeeperException, InterruptedException {
        zooKeeper.getChildren("/watcher3", new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                logger.info("节点路径:" + event.getPath());
                logger.info("事件类型:" + event.getType());
            }
        });
        Thread.sleep(50000);
    }

    /**
     * 3. watcher重复监听
     *
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void watcherGetChildren03() throws KeeperException, InterruptedException {
        Watcher watcher = new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                try {
                    logger.info("节点路径:" + event.getPath());
                    logger.info("事件类型:" + event.getType());
                    if (event.getType() == Event.EventType.NodeChildrenChanged) {
                        zooKeeper.getChildren("/watcher3", this);
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        };
        zooKeeper.getChildren("/watcher3", watcher);
        Thread.sleep(50000);
    }

    /**
     * 同时注册多个watcher
     *
     * @throws KeeperException
     * @throws InterruptedException
     */
    public void watcherGetChildren04() throws KeeperException, InterruptedException {
        // 多个监视器对象
        zooKeeper.getChildren("/watcher3", new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                try {
                    logger.info("节点路径:" + event.getPath());
                    logger.info("事件类型:" + event.getType());
                    if (event.getType() == Event.EventType.NodeChildrenChanged) {
                        zooKeeper.getChildren("/watcher3", this);
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        });

        zooKeeper.getChildren("/watcher3", new Watcher() {
            @Override
            public void process(WatchedEvent event) {
                try {
                    logger.info("节点路径:" + event.getPath());
                    logger.info("事件类型:" + event.getType());
                    if (event.getType() == Event.EventType.NodeChildrenChanged) {
                        zooKeeper.getChildren("/watcher3", this);
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        });
        Thread.sleep(50000);
    }

    public static void main(String[] args) throws KeeperException, InterruptedException {
        ZookeeperWatcherGetChildren zookeeperWatcherGetChildren = new ZookeeperWatcherGetChildren();
        zookeeperWatcherGetChildren.watcherGetChildren01();
        zookeeperWatcherGetChildren.watcherGetChildren02();
        zookeeperWatcherGetChildren.watcherGetChildren03();
        zookeeperWatcherGetChildren.watcherGetChildren04();
    }

}

同理,还是分四种情况分别讨论一下获取子节点变化事件监听:

【a】使用连接对象中的watcher

[zk: localhost:2181(CONNECTED) 28] create /watcher3/node1 "node1" 
Created /watcher3/node1

后端日志如下,可以看到成功监听到节点变化事件。

10:05:44.041 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 连接服务端成功...
10:05:44.041 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 节点路径:/watcher3
10:05:44.041 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 事件类型:NodeChildrenChanged

【b】自定义watcher

[zk: localhost:2181(CONNECTED) 29] create /watcher3/node2 "node2"
Created /watcher3/node2

后端日志如下,可以看到成功监听到节点变化事件。

10:06:28.390 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 节点路径:/watcher3
10:06:28.390 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 事件类型:NodeChildrenChanged

【c】watcher重复监听

[zk: localhost:2181(CONNECTED) 30] ls /watcher3
[node2, node1]
[zk: localhost:2181(CONNECTED) 31] delete /watcher3/node1
[zk: localhost:2181(CONNECTED) 32] delete /watcher3/node2
[zk: localhost:2181(CONNECTED) 33] ls /watcher3
[]

后端日志如下,可以看到成功监听到节点变化事件。

10:07:03.438 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 节点路径:/watcher3
10:07:03.438 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 事件类型:NodeChildrenChanged

10:07:05.646 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 节点路径:/watcher3
10:07:05.646 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 事件类型:NodeChildrenChanged

【d】同时注册多个watcher

[zk: localhost:2181(CONNECTED) 36] create /watcher3/node2 "node2"
Created /watcher3/node2

后端日志如下,可以看到成功监听到节点变化事件。

10:09:00.294 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 节点路径1:/watcher3
10:09:00.294 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 事件类型1:NodeChildrenChanged

10:09:00.295 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 节点路径2:/watcher3
10:09:00.295 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.watcher.ZookeeperWatcherGetChildren - 事件类型2:NodeChildrenChanged

八、总结

本篇文章主要总结了zookeeper中事件监听机制的概念、特性以及架构,最后结合案例详细说明了zookeeper中查看节点、查看子节点以及exists监听的使用方法,在工作中,zookeeper的监听可以拿来做消息的订阅以及发布功能,类如分布式配置中心等等。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付 19.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值