Zookeeper的API中的getData、getChildren和exists均可选择在读取的znode 上设置监视点。使用监视点,我们可以使用Watcher接口在process(WatchedEvent event)中捕获event
1. WatchEvent说明
- zk会话状态:KeeperState
- 事件类型:EventType
示例代码:
@Override
public void process(WatchedEvent watchedEvent) {
System.out.println("ZNodeWatcher Process Event:"+watchedEvent);
//获取会话状态
Event.KeeperState ks = watchedEvent.getState();
//获取事件状态
Event.EventType ev = watchedEvent.getType();
}
2. 监视点类型
监视点类型 | 设置方法 |
---|---|
NodeCreate | exists |
NodeDelete | exists \ getData |
NodeDataChanged | getData |
NodeChildrenChanged | getChildren |
例如:
//getdata 使用自定义watcher设置监视点
public byte[] getData(String path, Watcher watcher, Stat stat)
//使用默认watcher设置监视点
public byte[] getData(String path, boolean watch, Stat stat)
对于第二种与第一种的不同只是采用了默认的watcher
第二种方法源码:
public byte[] getData(String path, boolean watch, Stat stat) throws KeeperException, InterruptedException {
return this.getData(path, watch ? this.watchManager.defaultWatcher : null, stat);
}
3. 使用exists添加监视点
- 构造一个节点的监视点
Watcher nodeExistsWatcher= new Watcher() {
@Override
public void process(WatchedEvent event) {
String msg = "Node Exists Watcher Event:"+event.toString();
System.out.println(msg);
if(event.getType() == Event.EventType.NodeDeleted){
System.out.println(">> 节点:"+watchNode+" 被删除!");
assert watchNode.equals(event.getPath());
//监视点被触发一次就会失效,因此要重新添加
addExistsWatch();
}else if(event.getType() == Event.EventType.NodeCreated){
System.out.println(">> 节点:"+watchNode+" 被添加!");
assert watchNode.equals(event.getPath());
//节点添加后重新添加监视点
addExistsWatch();
}
}
};
- 构造一个创建监视点的回调方法
AsyncCallback.StatCallback nodeExistsCallback = new AsyncCallback.StatCallback() {
@Override
public void processResult(int i, String s, Object o, Stat stat) {
String msg = "Node Exists Callback: Code:"+i+" Path:"+s;
System.out.println(msg);
switch (KeeperException.Code.get(i)){
case CONNECTIONLOSS:
//连接丢失重新添加监视点
System.out.println("连接丢失!重新添加监视点!");
addExistsWatch();
break;
case OK:
System.out.println("OK,Stat:"+stat);
break;
case NONODE:
System.out.println("NONODE");
break;
case NODEEXISTS:
System.out.println("NODEEXISTS");
break;
default:
break;
}
}
};
- 创建监视点
public void addExistsWatch(){
zk.exists(watchNode,
nodeExistsWatcher,
nodeExistsCallback,
null
);
}
注意
4. 监视点是单次触发,既触发一次后就失效,因此,我们在 nodeExistsWatcher的 process 方法中触发一次后又重新添加;
5. exists方法仅能触发NodeDeleted,和NodeCreated,如果想触发NodeDataChanged 和NodeChildrenChanged还需要添加getData和getChildren方法
public void addNodeWatch() {
Stat stat = new Stat();
try{
byte data[] = zk.getData(watchNode,
nodeWatcher,
stat
);
String v = new String(data);
System.out.println(">>增加监视点,节点:"+watchNode+" 值:"+v);
}catch (KeeperException.NoNodeException ex){
System.out.println(">>添加节点监控点异常,节点:"+watchNode+" 不存在!");
}catch (KeeperException.ConnectionLossException ex){
ex.printStackTrace();
}catch (KeeperException ex){
ex.printStackTrace();
}catch (InterruptedException ex){
ex.printStackTrace();
}
}
public void addChildrenNodeWatch() {
Stat stat = new Stat();
try{
List<String> nodes = zk.getChildren(watchNode,
nodeWatcher,
stat
);
System.out.println(">>增加监视点,节点:"+watchNode+" 子节点列表:");
for (String node:nodes) {
System.out.println(">>子节点:"+node);
}
}catch (KeeperException.NoNodeException ex){
System.out.println(">>添加节点监控点异常,节点:"+watchNode+" 不存在!");
}catch (KeeperException.ConnectionLossException ex){
ex.printStackTrace();
}catch (KeeperException ex){
ex.printStackTrace();
}catch (InterruptedException ex){
ex.printStackTrace();
}
}
重新定义nodewatch,增加对NodeDataChanged 和NodeChildrenChanged的监视
Watcher nodeWatcher = new Watcher() {
@Override
public void process(WatchedEvent event) {
String msg = "Node Exists Watcher Event:"+event.toString();
System.out.println(msg);
if(event.getType() == Event.EventType.NodeDeleted){
System.out.println(">> 节点:"+watchNode+" 被删除!");
assert watchNode.equals(event.getPath());
//节点删除后重新添加监视点
addExistsWatch();
}else if(event.getType() == Event.EventType.NodeCreated){
System.out.println(">> 节点:"+watchNode+" 被添加!");
assert watchNode.equals(event.getPath());
//节点创建后可以增加getData和getChild方法的监视点
addNodeWatch();
addChildrenNodeWatch();
}else if(event.getType() == Event.EventType.NodeDataChanged){
System.out.println(">> 节点:"+watchNode+" 值修改!");
assert watchNode.equals(event.getPath());
//NodeDataChanged触发后重新添加监视点
addNodeWatch();
}else if(event.getType() == Event.EventType.NodeChildrenChanged){
System.out.println(">> 节点:"+watchNode+" 子节点变化!");
assert watchNode.equals(event.getPath());
//NodeChildrenChanged触发后重新添加监视点
addChildrenNodeWatch();
}
}
};