Zookeeper之事件监听机制
作者:互联网
目录
一、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的监听可以拿来做消息的订阅以及发布功能,类如分布式配置中心等等。
标签:main,zookeeper,wsh,Zookeeper,监听,节点,机制,watcher,event 来源: https://blog.csdn.net/Weixiaohuai/article/details/112864979