ZooKeeper中实现对接点的监控,需要实现Watcher接口类,实现其中的process方法
public class WatcherDemo implements Watcher{
public void process(WatchedEvent event) {
}
}
WatcherEvent对如下状态进行监听
1. ZooKeeper会话状态:Disconnected,SyncConnected,AuthFailed,ConnectedReadOnly,SaslAuthenticated和Expired
2. 事件类型:NodeCreated,NodeDeleted,NodeDataChanged,NodeChildrenChanged和None
3. 事件类型不是None时,返回一个znode路径
/**
* @author Eason
* @create 2018-04-07 21:41
**/
public class WatcherDemo implements Watcher {
public void process(WatchedEvent event) {
System.out.println("Enter the process method,the event is :"+event);
Event.EventType type = event.getType();
switch (type) {
case NodeDeleted:
System.out.println("新建节点:" + event.getPath());
}
}
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
String connectionString = "192.168.1.6:2181,192.168.1.6:2182,192.168.1.6:2183";
ZooKeeper zooKeeper = new ZooKeeper(connectionString, 15 * 1000, new WatcherDemo(), false);
zooKeeper.create("/myEphmeralPath1", "random".getBytes(), OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
TimeUnit.SECONDS.sleep(60);
zooKeeper.close();
}
}
执行完成后 控制台输出
Connected to the target VM, address: '127.0.0.1:50459', transport: 'socket'
Enter the process method,the event is :WatchedEvent state:SyncConnected type:None path:null
Disconnected from the target VM, address: '127.0.0.1:50459', transport: 'socket'
为什么没有监控到节点的创建呢?
首先,我们在创建ZK连接时指定了一个Watcher,但是这个Watcher指监控到了ZK连接成功的状态SyncConnected.这里同样有一个问题,为什么关闭客户端时没有监控到Disconnected事件呢.对于这个问题,个人理解是因为当前客户端失去连接,Watcher失效,在debug模式下使用同一个Watcher可以监控到Disconnected事件
/**
* @author Eason
* @create 2018-04-07 21:41
**/
public class WatcherDemo implements Watcher {
public void process(WatchedEvent event) {
System.out.println("Enter the process method,the event is :"+event);
Event.EventType type = event.getType();
switch (type) {
case NodeDeleted:
System.out.println("新建节点:" + event.getPath());
}
}
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
String connectionString = "192.168.1.6:2181,192.168.1.6:2182,192.168.1.6:2183";
ZooKeeper zooKeeper = new ZooKeeper(connectionString, 15 * 1000, new WatcherDemo(), false);
ZooKeeper zooKeeper1 = new ZooKeeper(connectionString, 15 * 1000, new WatcherDemo(), false);
zooKeeper.create("/myEphmeralPath1", "random".getBytes(), OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
zooKeeper.close();
TimeUnit.SECONDS.sleep(60);
}
}
控制台输出
Enter the process method,the event is :WatchedEvent state:SyncConnected type:None path:null
Enter the process method,the event is :WatchedEvent state:SyncConnected type:None path:null
Enter the process method,the event is :WatchedEvent state:Disconnected type:None path:null
Enter the process method,the event is :WatchedEvent state:Expired type:None path:null
注意的是需要debug模式下才可以看到输出结果,具体原因不清楚.
现在回到第一个问题,如何对创建节点设置监控呢?
首先看一下create有关的API
public String create(final String path, byte data[], List acl, CreateMode createMode)
public void create(final String path, byte data[], List acl,CreateMode createMode, StringCallback cb, Object ctx)
可以看到,create方法是没有Watcher相关方法的,因此,基于判断没有就创建的思想,可以使用exist API来设置一个监视点
/**
* @author Eason
* @create 2018-04-07 21:41
**/
public class WatcherDemo01 implements Watcher {
public void process(WatchedEvent event) {
System.out.println("Enter the process method,the event is :" + event);
Event.EventType type = event.getType();
switch (type) {
case NodeCreated:
System.out.println("新建节点:" + event.getPath());
case NodeDeleted:
System.out.println("删除节点:" + event.getPath());
case NodeDataChanged:
System.out.println("修改节点:" + event.getPath());
case NodeChildrenChanged:
System.out.println("子节点:" + event);
}
}
public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
WatcherDemo01 watcherDemo = new WatcherDemo01();
String connectionString = "192.168.1.6:2181,192.168.1.6:2182,192.168.1.6:2183";
ZooKeeper zooKeeper = new ZooKeeper(connectionString, 15 * 1000, watcherDemo, false);
String path = "/watcherdemo01";
String childPath = "/watcherdemo01/child01";
Stat stat = zooKeeper.exists(path, watcherDemo);
if (stat == null) {
zooKeeper.create(path, "random".getBytes(), OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
if (stat != null) {
zooKeeper.delete(path, stat.getVersion());
}
TimeUnit.SECONDS.sleep(5);
zooKeeper.close();
}
}
下面是对如何设置监控点的总结
- 对于NodeCreated 通过exists API设置
- 对于NodeDeleted 通过exists 和 getData()设置
- 对于NodeDataChanged 通过exists或getData设置
- 对于NodeChildrenChanged 通过getChildren设置
首先要区分通知和回调的区别,通知是ZooKeeper中注册了监视点的客户端收到的事件报告消息,而回调是基于异步思想的,通过回调函数来确定操作的完成情况
/**
* @author Eason
* @create 2018-04-07 22:47
**/
public class CallBackDemo implements Watcher {
public static void main(String[] args) throws InterruptedException, IOException {
String connectionString = "192.168.1.6:2181,192.168.1.6:2182,192.168.1.6:2183";
ZooKeeper zooKeeper = new ZooKeeper(connectionString, 15 * 1000, new CallBackDemo(), false);
String path = "/callBackDemo";
String params = "123";
zooKeeper.create(path, "".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT, new AsyncCallback.StringCallback() {
public void processResult(int rc, String path, Object ctx, String name) {
System.out.println("Object ctx 参数对应于create 方法最后一个参数");
System.out.println(ctx.toString());
KeeperException.Code code = KeeperException.Code.get(rc);
switch (code) {
case OK:
case NOAUTH:
case NONODE:
case APIERROR:
case NOTEMPTY:
case AUTHFAILED:
case BADVERSION:
case INVALIDACL:
case NODEEXISTS:
case NOTREADONLY:
case SYSTEMERROR:
case BADARGUMENTS:
case SESSIONMOVED:
case UNIMPLEMENTED:
case CONNECTIONLOSS:
case SESSIONEXPIRED:
case INVALIDCALLBACK:
case MARSHALLINGERROR:
case OPERATIONTIMEOUT:
case DATAINCONSISTENCY:
case RUNTIMEINCONSISTENCY:
case NOCHILDRENFOREPHEMERALS:
}
}
}, params);
TimeUnit.SECONDS.sleep(10);
}
public void process(WatchedEvent event) {
}
}
注意Object ctx参数,具体状态吗不再赘述