原生的ZooKeeper Wacher是一次性的:一个Wacher一旦触发就会被移出,如果你想要反复使用Wacher,就要在Wacher被移除后重新注册,使用起来很麻烦,Curator在这方面做了优化,Curator引入了Cache的概念用来实现对ZooKeeper服务器端进行事件监听。Cache是Curator对事件监听的包装,其对事件的监听可以近似看做是一个本地缓存视图和远程ZooKeeper视图的对比过程。而且Curator会自动的再次监听,我们就不需要自己手动的重复监听了。
Curator中的cache共有三种:
1.NodeCache(监听和缓存根节点变化) 只监听单一个节点(变化 添加,修改,删除).
2.PathChildrenCache(监听和缓存子节点变化) 监听这个节点下的所有子节点(变化 添加,修改,删除).
3.TreeCache(监听和缓存根节点变化和子节点变化) NodeCache+ PathChildrenCache 监听当前节点及其下的所有子节点的变化.
使用方法:
1.引入maven依赖
<!--zookeeper CuratorFramework 是Netflix公司开发一款连接zookeeper服务的框架,通过封装的一套高级API 简化了ZooKeeper的操作,提供了比较全面的功能,除了基础的节点的操作,节点的监听,还有集群的连接以及重试。-->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.1</version>
</dependency>
2.启动zookeeper服务器,默认端口2181.
下面直接上代码:
1.NodeCache
//创建重试策略
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,1);
//创建客户端
CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", 1000, 1000, retryPolicy);
//开启客户端
client.start();
System.out.println("连接成功");
//创建节点数据监听对象
final NodeCache nodeCache = new NodeCache(client, "/hello");
//开始缓存
/**
* start参数为true:可以直接获取监听的节点,System.out.println(nodeCache.getCurrentData());为ChildData{path='/aa', stat=607,765,1580205779732,1580973376268,2,1,0,0,5,1,608
, data=[97, 98, 99, 100, 101]}
* 参数为false:不可以获取监听的节点,System.out.println(nodeCache.getCurrentData());为null
*/
nodeCache.start(true);
System.out.println(nodeCache.getCurrentData());
//添加监听对象
nodeCache.getListenable().addListener(new NodeCacheListener() {
//如果节点数据有变化,会回调该方法
public void nodeChanged() throws Exception {
String data = new String(nodeCache.getCurrentData().getData());
System.out.println("数据Watcher:路径=" + nodeCache.getCurrentData().getPath()
+ ":data=" + data);
}
});
//阻塞
System.in.read();
2.PathChildrenCache
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,1);
CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", 1000, 1000, retryPolicy);
client.start();
//监听指定节点的子节点变化情况包括新增子节点 子节点数据变更 和子节点删除
//true表示用于配置是否把节点内容缓存起来,如果配置为true,客户端在接收到节点列表变更的同时,也能够获取到节点的数据内容(即:event.getData().getData())ͺ如果为false 则无法取到数据内容(即:event.getData().getData())
PathChildrenCache childrenCache = new PathChildrenCache(client,"/hello",true);
/**
* NORMAL: 普通启动方式, 在启动时缓存子节点数据
* POST_INITIALIZED_EVENT:在启动时缓存子节点数据,提示初始化
* BUILD_INITIAL_CACHE: 在启动时什么都不会输出
* 在官方解释中说是因为这种模式会在start执行执行之前先执行rebuild的方法,而rebuild的方法不会发出任何事件通知。
*/
childrenCache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);
System.out.println(childrenCache.getCurrentData());
//添加监听
childrenCache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
if(event.getType() == PathChildrenCacheEvent.Type.CHILD_UPDATED){
System.out.println("子节点更新");
System.out.println("节点:"+event.getData().getPath());
System.out.println("数据" + new String(event.getData().getData()));
}else if(event.getType() == PathChildrenCacheEvent.Type.INITIALIZED ){
System.out.println("初始化操作");
}else if(event.getType() == PathChildrenCacheEvent.Type.CHILD_REMOVED ){
System.out.println("删除子节点");
System.out.println("节点:"+event.getData().getPath());
System.out.println("数据" + new String(event.getData().getData()));
}else if(event.getType() == PathChildrenCacheEvent.Type.CHILD_ADDED ){
System.out.println("添加子节点");
System.out.println("节点:"+event.getData().getPath());
System.out.println("数据" + new String(event.getData().getData()));
}else if(event.getType() == PathChildrenCacheEvent.Type.CONNECTION_SUSPENDED ){
System.out.println("连接失效");
}else if(event.getType() == PathChildrenCacheEvent.Type.CONNECTION_RECONNECTED ){
System.out.println("重新连接");
}else if(event.getType() == PathChildrenCacheEvent.Type.CONNECTION_LOST ){
System.out.println("连接失效后稍等一会儿执行");
}
}
});
System.in.read(); // 使线程阻塞
3.TreeCache
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,1);
CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", 1000, 1000, retryPolicy);
client.start();
TreeCache treeCache = new TreeCache(client,"/hello");
treeCache.start();
System.out.println(treeCache.getCurrentData("/hello"));
treeCache.getListenable().addListener(new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
if(event.getType() == TreeCacheEvent.Type.NODE_ADDED){
System.out.println(event.getData().getPath() + "节点添加");
}else if (event.getType() == TreeCacheEvent.Type.NODE_REMOVED){
System.out.println(event.getData().getPath() + "节点移除");
}else if(event.getType() == TreeCacheEvent.Type.NODE_UPDATED){
System.out.println(event.getData().getPath() + "节点修改");
}else if(event.getType() == TreeCacheEvent.Type.INITIALIZED){
System.out.println("初始化完成");
}else if(event.getType() ==TreeCacheEvent.Type.CONNECTION_SUSPENDED){
System.out.println("连接过时");
}else if(event.getType() ==TreeCacheEvent.Type.CONNECTION_RECONNECTED){
System.out.println("重新连接");
}else if(event.getType() ==TreeCacheEvent.Type.CONNECTION_LOST){
System.out.println("连接过时一段时间");
}
}
});
System.in.read();