1. 基于watch实现监听
利用Watcher来对节点进行监听操作,但此监听操作只能监听一次,与原生API并无太大差异。如有典型业务场景需要使用可考虑,但一般情况不推荐使用。
下面是具体的使用demo:
public class CuratorWatchEvent {
public static CuratorFramework build(){
CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
.connectString("172.30.241.205:2181")
.namespace(ZKConstant.ZK_NAMESPACE)
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
.build();
curatorFramework.start();
return curatorFramework;
}
public static void main(String[] args) throws Exception{
String path = "/watchtest";
CuratorFramework client = CuratorWatchEvent.build();
client.create().creatingParentsIfNeeded()
.withMode(CreateMode.EPHEMERAL)
.forPath(path);
build().getData().usingWatcher(new Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("监听器watchedEvent:" + watchedEvent);
}
}).forPath(path);
client.setData().forPath(path,"new content".getBytes());
// 第二次变更节点数据
client.setData().forPath(path,"second content".getBytes());
client.close();
}
}
2. Listener
也是一次性的监听操作,使用后就无法在继续监听了
package zookeeper.curator.watcher;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.CuratorEvent;
import org.junit.Test;
import zookeeper.curator.CuratorBaseOperations;
@Slf4j
public class CuratorListenerTest extends CuratorBaseOperations{
@Test
public void testCuratorListener() throws Exception {
CuratorFramework curatorFramework = getCuratorFramework();
curatorFramework.getCuratorListenable().addListener((CuratorFramework client, CuratorEvent event)->{
log.info(" things changed1: event: {}, {} ",event.getType().name(),event);
});
String path = "/test";
createIfNeed(path);
log.info("start to change data for path :{}" ,path);
curatorFramework.setData().inBackground().forPath(path,"xxx1".getBytes());
log.info("start to change data for path :{} again" ,path);
curatorFramework.setData().inBackground().forPath(path,"xxx2".getBytes());
curatorFramework.create().inBackground().forPath("/test456","test456".getBytes());
}
}
3. 基于cache实现监听
cache是一种缓存机制,Cache事件监听可以理解为一个本地缓存视图与远程Zookeeper视图的对比过程。Cache提供了反复注册的功能。
curator支持的cache种类有3种
-
Path Cache
Path Cache用来观察ZNode的子节点并缓存状态,如果ZNode的子节点被创建,更新或者删除,那么Path Cache会更新缓存,并且触发事件给注册的监听器。Path Cache是通过PathChildrenCache类来实现的,监听器注册是通过PathChildrenCacheListener。
-
Node Cache
Node Cache用来观察ZNode自身,如果ZNode节点本身被创建,更新或者删除,那么Node Cache会更新缓存,并触发事件给注册的监听器。Node Cache是通过NodeCache类来实现的,监听器对应的接口为NodeCacheListener。
-
Tree Cache
可以看做是上两种的合体,Tree Cache观察的是ZNode及子节点。
3.1 node cache:
NodeCache 对某一个节点进行监听:
public NodeCache(CuratorFramework client,
String path)
Parameters:
client - the client
path - path to cache
可以通过注册监听器来实现,对当前节点数据变化的处理
public void addListener(NodeCacheListener listener)
Add a change listener
Parameters:
listener - the listener
完整示例:
package zookeeper.curator.cache;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.NodeCache;
import org.apache.curator.framework.recipes.cache.NodeCacheListener;
import org.junit.Test;
import zookeeper.curator.CuratorStandaloneBase;
@Slf4j
public class NodeCacheTest extends CuratorStandaloneBase{
public static final String NODE_CACHE="/node-cache";
@Test
public void testNodeCacheTest() throws Exception {
CuratorFramework curatorFramework = getCuratorFramework();
createIfNeed(NODE_CACHE);
NodeCache nodeCache = new NodeCache(curatorFramework, NODE_CACHE);
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
log.info("{} path nodeChanged: ",NODE_CACHE);
printNodeData();
}
});
nodeCache.start();
}
public void printNodeData() throws Exception {
CuratorFramework curatorFramework = getCuratorFramework();
byte[] bytes = curatorFramework.getData().forPath(NODE_CACHE);
log.info("data: {}",new String(bytes));
}
}
3.2 path cache:
PathChildrenCache 会对子节点进行监听,但是不会对二级子节点进行监听:
public PathChildrenCache(CuratorFramework client,
String path,
boolean cacheData)
Parameters:
client - the client
path - path to watch
cacheData - if true, node contents are cached in addition to the stat
可以通过注册监听器来实现,对当前节点的子节点数据变化的处理:
public void addListener(PathChildrenCacheListener listener)
Add a change listener
Parameters:
listener - the listener
完整示例:
package zookeeper.curator.cache;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.junit.Test;
import zookeeper.curator.CuratorBaseOperations;
@Slf4j
public class PathCacheTest extends CuratorBaseOperations{
public static final String PATH="/path-cache";
@Test
public void testPathCache() throws Exception {
CuratorFramework curatorFramework = getCuratorFramework();
createIfNeed(PATH);
PathChildrenCache pathChildrenCache = new PathChildrenCache(curatorFramework, PATH, true);
pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
log.info("event: {}",event);
}
});
// 如果设置为true则在首次启动时就会缓存节点内容到Cache中
pathChildrenCache.start(true);
}
}
3.3 tree cache:
TreeCache 使用一个内部类TreeNode来维护这个一个树结构。并将这个树结构与ZK节点进行了映射。所以TreeCache 可以监听当前节点下所有节点的事件。
public TreeCache(CuratorFramework client,
String path,
boolean cacheData)
Parameters:
client - the client
path - path to watch
cacheData - if true, node contents are cached in addition to the stat
可以通过注册监听器来实现,对当前节点的子节点,及递归子节点数据变化的处理:
public void addListener(TreeCacheListener listener)
Add a change listener
Parameters:
listener - the listener
完整示例:
package zookeeper.curator.cache;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.junit.Test;
import zookeeper.curator.CuratorBaseOperations;
import java.util.Map;
@Slf4j
public class TreeCacheTest extends CuratorBaseOperations{
public static final String TREE_CACHE="/tree-path";
@Test
public void testTreeCache() throws Exception {
CuratorFramework curatorFramework = getCuratorFramework();
createIfNeed(TREE_CACHE);
TreeCache treeCache = new TreeCache(curatorFramework, TREE_CACHE);
treeCache.getListenable().addListener(new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
log.info(" tree cache: {}",event);
Map<String, ChildData> currentChildren = treeCache.getCurrentChildren(TREE_CACHE);
log.info("currentChildren: {}",currentChildren);
}
});
treeCache.start();
}
}