zookeeper如何永久监听
2016-07-24 13:26
232 查看
一 回调基础知识
znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的集中管理,集群管理,分布式锁等等。
将APP1的所有配置配置到/APP1 znode下,APP1所有机器一启动就对/APP1这个节点进行监控(zk.exist("/APP1",true)),并且实现回调方法Watcher,那么在zookeeper上/APP1 znode节点下数据发生变化的时候,每个机器都会收到通知,Watcher方法将会被执行,那么应用再取下数据即可(zk.getData("/APP1",false,null));
下面表格列出了写操作与ZK内部产生的事件的对应关系:
而ZK内部的写事件与所触发的watcher的对应关系如下:
综合上面两个表,我们可以总结出各种写操作可以触发哪些watcher,如下表所示:
如果发生session close、authFail和invalid,那么所有类型的wather都会被触发
zkClient除了做了一些便捷包装之外,对watcher使用做了一点增强。比如subscribeChildChanges实际上是通过exists和getChildren关注了两个事件。这样当create(“/path”)时,对应path上通过getChildren注册的listener也会被调用。另外subscribeDataChanges实际上只是通过exists注册了事件。因为从上表可以看到,对于一个更新,通过exists和getData注册的watcher要么都会触发,要么都不会触发。
getData,getChildren(),exists()这三个方法可以针对参数中的path设置watcher,当path对应的Node 有相应变化时,server端会给对应的设置了watcher的client 发送一个一次性的触发通知事件。客户端在收到这个触发通知事件后,可以根据自己的业务逻辑进行相应地处理。
注意这个watcher的功能是一次性的,如果还想继续得到watcher通知,在处理完事件后,要重新register。
二 测试watcher回调机制
三 永久回调
3类事件触发wather后就不再作用,也就是所谓的(一次作用),但是,如何永久监听呢?这需要我们再程序逻辑上进行控制,网上有更好的办法,但是,在简单的应用中,可以再wather方法里面再设置监听,这个方法很笨,但是,很有效,达到了预期的效果。
znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的集中管理,集群管理,分布式锁等等。
//创建一个Zookeeper实例,第一个参数为目标服务器地址和端口,第二个参数为Session超时时间,第三个为节点变化时的回调方法 ZooKeeper zk = new ZooKeeper("127.0.0.1:2181", 500000,new Watcher() { // 监控所有被触发的事件 public void process(WatchedEvent event) { //dosomething } });
将APP1的所有配置配置到/APP1 znode下,APP1所有机器一启动就对/APP1这个节点进行监控(zk.exist("/APP1",true)),并且实现回调方法Watcher,那么在zookeeper上/APP1 znode节点下数据发生变化的时候,每个机器都会收到通知,Watcher方法将会被执行,那么应用再取下数据即可(zk.getData("/APP1",false,null));
下面表格列出了写操作与ZK内部产生的事件的对应关系:
event For “/path” | event For “/path/child” | |
create(“/path”) | EventType.NodeCreated | NA |
delete(“/path”) | EventType.NodeDeleted | NA |
setData(“/path”) | EventType.NodeDataChanged | NA |
create(“/path/child”) | EventType.NodeChildrenChanged | EventType.NodeCreated |
delete(“/path/child”) | EventType.NodeChildrenChanged | EventType.NodeDeleted |
setData(“/path/child”) | NA | EventType.NodeDataChanged |
event For “/path” | defaultWatcher | exists (“/path”) | getData (“/path”) | getChildren (“/path”) |
EventType.None | √ | √ | √ | √ |
EventType.NodeCreated | √ | √ | ||
EventType.NodeDeleted | √(不正常) | √ | ||
EventType.NodeDataChanged | √ | √ | ||
EventType.NodeChildrenChanged | √ |
“/path” | “/path/child” | |||||
exists | getData | getChildren | exists | getData | getChildren | |
create(“/path”) | √ | √ | ||||
delete(“/path”) | √ | √ | √ | |||
setData(“/path”) | √ | √ | ||||
create(“/path/child”) | √ | √ | √ | |||
delete(“/path/child”) | √ | √ | √ | √ | ||
setData(“/path/child”) | √ | √ |
zkClient除了做了一些便捷包装之外,对watcher使用做了一点增强。比如subscribeChildChanges实际上是通过exists和getChildren关注了两个事件。这样当create(“/path”)时,对应path上通过getChildren注册的listener也会被调用。另外subscribeDataChanges实际上只是通过exists注册了事件。因为从上表可以看到,对于一个更新,通过exists和getData注册的watcher要么都会触发,要么都不会触发。
getData,getChildren(),exists()这三个方法可以针对参数中的path设置watcher,当path对应的Node 有相应变化时,server端会给对应的设置了watcher的client 发送一个一次性的触发通知事件。客户端在收到这个触发通知事件后,可以根据自己的业务逻辑进行相应地处理。
注意这个watcher的功能是一次性的,如果还想继续得到watcher通知,在处理完事件后,要重新register。
二 测试watcher回调机制
// Watcher实例 Watcher wh = new Watcher() { public void process(WatchedEvent event) { System.out.println("回调watcher实例: 路径" + event.getPath() + " 类型:" + event.getType()); } }; ZooKeeper zk = new ZooKeeper("10.15.82.166:3351", 500000, wh); System.out.println("---------------------"); // 创建一个节点root,数据是mydata,不进行ACL权限控制,节点为永久性的(即客户端shutdown了也不会消失) zk.exists("/root", true); zk.create("/root", "mydata".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("---------------------"); // 在root下面创建一个childone znode,数据为childone,不进行ACL权限控制,节点为永久性的 zk.exists("/root/childone", true); zk.create("/root/childone", "childone".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); System.out.println("---------------------"); // 删除/root/childone这个节点,第二个参数为版本,-1的话直接删除,无视版本 zk.exists("/root/childone", true); zk.delete("/root/childone", -1); System.out.println("---------------------"); zk.exists("/root", true); zk.delete("/root", -1); System.out.println("---------------------"); // 关闭session zk.close();
--------------------- 回调watcher实例: 路径null 类型:None 回调watcher实例: 路径/root 类型:NodeCreated --------------------- 回调watcher实例: 路径/root/childone 类型:NodeCreated --------------------- 回调watcher实例: 路径/root/childone 类型:NodeDeleted --------------------- 回调watcher实例: 路径/root 类型:NodeDeleted ---------------------
三 永久回调
3类事件触发wather后就不再作用,也就是所谓的(一次作用),但是,如何永久监听呢?这需要我们再程序逻辑上进行控制,网上有更好的办法,但是,在简单的应用中,可以再wather方法里面再设置监听,这个方法很笨,但是,很有效,达到了预期的效果。
Watcher wh = new Watcher() { public void process(WatchedEvent event) { Log.AC_DEBUG("触发回调watcher实例: 路径" + event.getPath() + " 类型:" + event.getType()); if (event.getType() == EventType.None) { try { // // 判断userauth权限是否能访问userpath String auth_type = "digest"; zk.addAuthInfo(auth_type, userauth.getBytes()); zk.getData(userpath, null, null); } catch (Exception e) { // e.printStackTrace(); Log.AC_ERROR("get node faild:userpath=" + userpath + ",auth=" + userauth + " e:" + e.getMessage()); return; } Log.AC_INFO("userpath=" + userpath + " userauth=" + userauth); } try { switchinfo = getallswitch(); // 更新userpath和匿名用户路径下的配置信息,监听这些节点 // 监听用户路径节点 Log.AC_DEBUG("lesson user=" + userpath + " node..."); zk.exists(userpath, true); // 监听匿名用户路径节点 Log.AC_DEBUG("lesson user=" + AnonymousUSERpath + " node..."); zk.exists(AnonymousUSERpath, true); // 监听用户路径下的开关节点 if (zk.exists(userpath, false) != null) { Log.AC_DEBUG("lesson user=" + userpath + " 's swich node..."); List<String> swnodes = zk.getChildren(userpath, true); // // 监听switch层节点的变化 Iterator<String> it_sw = swnodes.iterator(); while (it_sw.hasNext()) { String swpath = userpath + "/" + it_sw.next(); Log.AC_DEBUG("lesson user=" + swpath + " node..."); zk.exists(swpath, true); } } } catch (Exception e) { e.printStackTrace(); Log.AC_ERROR("lesson znode error:" + e.getMessage()); } } };
相关文章推荐
- [已验证]双卡手机下两种来电监听方法的一些问题。
- NodeJS Web应用监听sock文件实例
- jQuery绑定事件监听bind和移除事件监听unbind用法实例详解
- 全面解析Bootstrap中scrollspy(滚动监听)的使用方法
- Oracle监听器服务不能启动的解决方法
- Flex 自动获取焦点 监听全局键盘事件
- 深入浅析JavaScript中对事件的三种监听方式
- 有道JavaScript监听浏览器的问题
- Android中监听软键盘显示状态实现代码
- JavaScript绑定事件监听函数的通用方法
- Android实现信号强度监听的方法
- JavaScript监听文本框回车事件并过滤文本框空格的方法
- 浅析如何在tnsnames.ora中配置监听
- Shell脚本实现自动安装zookeeper
- 基于Zookeeper的使用详解
- js与jquery实时监听输入框值的oninput与onpropertychange方法
- js控制元素显示在屏幕固定位置及监听屏幕高度变化的方法
- Android 网络状态实时监听代码实例(一)
- Android广播接实现监听电话状态(电话的状态,拦截)
- android监听安装和卸载示例