Watch:
vt.
注视,注意;看守,监视;守候(机会等);密切注意
n.
表;值夜,值班;看守,监视;值班人员
vi.
观看;注视;守候;看守
Zookeeper的watch时间是一次性触发的,当watch监视的数据发生变化时,将信息通知给设置了该watch的client端,即watcher。所以,当watcher监视的数据发生了变化,那就有其对应的事件类型和状态类型。
事件类型(与Znode节点相关的):
EventType.NodeCreated //创建节点事件
EventType.NodeDataChanged //节点数据产生变化
EventType.NodeChildrenChanged //节点的子节点产生变化
EventType.NodeDeleted //删除节点事件
状态类型(与客户端示例相关的):
KeeperState.Disconnected //连接失败
KeeperState.SyncConnected //连接成功
KeeperState.AuthFailed //认证失败
KeeperState.Expired //认证过期
举个栗子:创建一个节点,此时应该有事件类型:NodeCreated,但这些应该是基于状态类型:SyncConnected,代码示例如下:
main:
//创建连接
zkWatcher.createConnection(CONNECTION_ADDR, SESSION_TIMEOUT);
try {
Thread.sleep(1*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//创建节点
if(zkWatcher.createPath(NODE_CHILDREN, System.currentTimeMillis()+"", true)) {
System.out.println();
}
while(true) {
}
createConnection:
//创建连接
public ZooKeeper createConnection(String connectAddr,int sessionTimeout) {
this.releaseConnection();
try {
zk = new ZooKeeper(connectAddr,sessionTimeout,this) ;
System.out.println("【Main】"+"开始连接ZooKeeper服务器");
//connectedSemaphore.wait();
} catch (IOException e) {
e.printStackTrace();
//} catch (InterruptedException e) {
// e.printStackTrace();
}
return zk;
}
createZnode:
//创建节点
//设置监控(由于watch都是一次性的,所以每次都需要设置监控)
try {
this.zk.exists(path, needWatch);
System.out.println(LOG_PREFIX_OF_MAIN+"节点创建成功,Path:"
+this.zk.create( /* 路径 */
path,
/* 数据 */
data.getBytes(),
/* 所有可见 */
Ids.OPEN_ACL_UNSAFE,
/* 持久节点 */
CreateMode.PERSISTENT)
+",content:"+data);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
上面代码中创建连接是所需要的“this”就是一个自定义的watcher,重写watcher的process方法,如下:
public void process(WatchedEvent event) {
System.out.println("进入process,Event is "+event);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(event == null) {
return ;
}
//连接状态
KeeperState keeperState = event.getState();
//事件类型
EventType eventType = event.getType();
//受影响的节点路径
String path = event.getPath();
//原子对象seq,记录进入process的次数
String logPrefix = "【Watcher - "+this.seq.incrementAndGet()+"】";
System.out.println(logPrefix + "收到Watcher通知");
System.out.println(logPrefix + "连接状态:"+keeperState.toString());
System.out.println(logPrefix + "事件类型:"+eventType.toString());
System.out.println(logPrefix + "受影响的节点路径:"+path);
/*
* Watcher四个状态:Disconnected、SyncConnected、AuthFailed、Expired
*/
//连接Zookeeper服务器
if(KeeperState.SyncConnected == keeperState) {
/*
* Watcher四个事件类型:NodeCreated、NodeDataChanged、NodeChildrenChanged、NodeDeleted
*/
//成功连接上ZK服务器,刚连接上Zookeeper服务器,所以事件类型为None
if(EventType.None == eventType) {
System.out.println(logPrefix + "成功连接上zk服务器");
//connectedSemaphore.countDown();
}
//创建节点
else if(EventType.NodeCreated == eventType) {
System.out.println(logPrefix+"创建节点");
try {
Thread.sleep(3*1000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
//更新节点数据
else if(EventType.NodeDataChanged == eventType) {
System.out.println(logPrefix+"更新节点数据信息");
try {
Thread.sleep(3*1000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
//更新节点的子节点
else if(EventType.NodeChildrenChanged == eventType) {
System.out.println(logPrefix+"更新节点的子节点");
try {
Thread.sleep(3*1000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
//删除节点
else if(EventType.NodeDeleted == eventType) {
System.out.println(logPrefix+"删除节点");
try {
Thread.sleep(3*1000);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
//没了
else {
System.out.println("Hello World");
}
}
//断开Zookeeper服务器
else if(KeeperState.Disconnected == keeperState) {
System.out.println(logPrefix+"断开Zookeeper服务器");
}
//连接认证失败
else if(KeeperState.AuthFailed == keeperState) {
System.out.println(logPrefix+"连接认证失败");
}
//连接认证过期
else if(KeeperState.Expired == keeperState) {
System.out.println(logPrefix+"连接认证过期");
}
//没了
else {
System.out.println("Hello World");
}
}
控制台打印创建节点信息:
Zookeeper服务器上对应节点创建成功:
备注:
1、将exists(String path, boolean watch)
的watch参数设置为false时,对于接下来的创建节点将不会被watch监控,控制台打印效果如下:
2、exists方法重载:exists(String path, Watcher watcher)
,即实例化一个新的watch来监听接下来对Zookeeper服务器的操作,只是此方式可以根据不同的场景灵活指定具体的watcher对象而不是使用原来的watcher。