HMZK3【Zookeeper Watch事件监听】
1 概念
-
ZooKeeper 允许用户在指定节点上注册一些Watcher,并且在一些特定事件触发的时候,ZooKeeper 服务端会将事件通知到感兴趣的客户端上去,该机制是 ZooKeeper 实现分布式协调服务的重要特性。
- 例如上图:用户在服务端的app1节点上注册了Watcher监听器,特殊事件比如节点数据变更,感兴趣的客户端app1会受到通知
-
ZooKeeper 中引入了Watcher机制来实现了发布/订阅功能能,能够让多个订阅者同时监听某一个对象,当一个对象自身状态变化时,会通知所有订阅者。
-
ZooKeeper 原生支持通过注册Watcher来进行事件监听,但是其使用并不是特别方便,需开发人员自己反复注册Watcher,较繁琐。
-
Curator引入了 Cache 来实现对 ZooKeeper 服务端事件的监听。
-
ZooKeeper提供了三种Watcher:
- NodeCache : 只是监听某一个特定的节点
- PathChildrenCache : 监控一个ZNode的子节点.
- TreeCache : 可以监控整个子树上的所有节点,类似于PathChildrenCache和NodeCache的组合
- 即当前节点及其所有孩子节点;兄弟节点及他们的孩子监控不到
2 实现
2.1NodeCache
2.2 PathChildrenCache
节点本身并不能被监听到,只能监听其孩子节点
2.3 TreeCache
2.4 源代码
package com.yppah.curator;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* @Author: haifei
* @Date: 2022/10/22 9:29
*/
public class CuratorWatcherTest {
private CuratorFramework client3;
@Before
public void testConnect() {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 10);
client3 = CuratorFrameworkFactory.builder()
.connectString("101.43.128.227:2181")
.sessionTimeoutMs(60 * 1000)
.connectionTimeoutMs(15 * 1000)
.retryPolicy(retryPolicy)
.namespace("ohh")
.build();
//这种命名空间的目录节点,在其下没有任何子节点时,不久该目录节点可能会被自动删除
client3.start();
}
@After
public void close() {
if (client3 != null) {
client3.close();
}
}
/**
* 给指定一个节点注册监听器
*/
@Test
public void testNodeCache() throws Exception {
// 1、创建NodeCache对象
final NodeCache nodeCache = new NodeCache(client3, "/app1");
// 2、注册监听
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
System.out.println("节点变化了:");
//获取修改节点后的数据
byte[] data = nodeCache.getCurrentData().getData();
String path = nodeCache.getCurrentData().getPath();
Stat stat = nodeCache.getCurrentData().getStat();
System.out.println(new String(data));
System.out.println(path);
System.out.println(stat);
}
});
// 3、开启监听(如果设置为true,则开启监听时加载缓冲数据)
nodeCache.start(true);
//测试用(因为正常运行Test方法会直接结束程序,监听不到变化)
while (true) {
}
}
/**
* 监听某节点的所有孩子节点
*/
@Test
public void testPathChildrenCache() throws Exception {
//1、创建监听对象
PathChildrenCache pathChildrenCache = new PathChildrenCache(client3, "/app2", true);
//2、绑定监听器
pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
System.out.println("子节点变化了:");
System.out.println(pathChildrenCacheEvent);
//监听子节点的数据变更,并拿到变更后的数据
//2-1 获取类型
PathChildrenCacheEvent.Type type = pathChildrenCacheEvent.getType();
//2-2 判断类型是否为update
if (type.equals(PathChildrenCacheEvent.Type.CHILD_UPDATED)) {
System.out.println("数据变化了:");
byte[] data = pathChildrenCacheEvent.getData().getData();
System.out.println(new String(data));
}
}
});
//3、开启监听
pathChildrenCache.start();
while (true) {
}
}
/**
* 监听某节点本身及其所有孩子节点
*/
@Test
public void testTreeCache() throws Exception {
//1、创建监听对象
TreeCache treeCache = new TreeCache(client3, "/app2");
//2、注册监听
treeCache.getListenable().addListener(new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
System.out.println("节点变化了:");
System.out.println(treeCacheEvent);
}
});
//3、开启监听
treeCache.start();
while (true) {
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!