首先,下面的表格是所有事件类型和触发条件,大体分为两类,一是连接状态事件(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事件!
可以看到,客户端与服务端成功建立会话触发了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处理的事件分为两类
一是连接状态事件,无需注册,一旦发生就会触发。
二是节点事件,需要注册才能触发,且一次注册只能触发一次。