1 watcher种类和事件种类

Watcher种类

1. zookeeper实例化时注入的默认Watcher

2. dataWatchers 一个Map<string Set<Watcher>>数据结构,保存调用getData时 注入的Watcher或者调用exist时path指定的节点存在

3. existWatchers 一个Map<string Set<Watcher>>数据结构,保存调用exits时对应的path节点不存在条件下注入的Watcher

4. childWatchers一个Map<string Set<Watcher>>数据结构,保存调用getChildren 时注入的Watcher

默认Watcher主要是处理连接建立成功,连接断了-会重连,SESSION失效-这个需要重新实例zookeeper对象这些事件

其他的三个Watcher都是MAP<String, SET<Watcher>>结构的,MAP中的KEY是zookeeper数据路径,当调用

exists,getData,getChildren函数时会需要传入一个Watcher,对应的path上的数据发生改变时,zookeeper服务器

会发送NOTIFY包给客户端,客户端在收到NOTIFY包后根据包指明的path和事件类别回调有关Watcher的process函数。

所有需要系统的管理这些Watcher,故分成三个MAP来管理这些Watcher。

当调用getData时将注入的Watcher加入到dataWatchers.get(path)的SET里面,调用childWatchers时一样。需要

重点注意的是当调用exists时,如果path不存在则加入到existWatchers.get(path)的SET里面,否则加入到

dataWatchers.get(path)的SET里面,这样做的原因是为了保持和客户端接收到NOTIFY包时处理一致。
Watch事件类型:

ZOO_CREATED_EVENT:节点创建事件,需要watch一个不存在的节点,当节点被创建时触发,此watch通过zoo_exists()设置

ZOO_DELETED_EVENT:节点删除事件,此watch通过zoo_exists()或zoo_get()设置

ZOO_CHANGED_EVENT:节点数据改变事件,此watch通过zoo_exists()或zoo_get()设置

ZOO_CHILD_EVENT:子节点列表改变事件,此watch通过zoo_get_children()或zoo_get_children2()设置

ZOO_SESSION_EVENT:会话失效事件,客户端与服务端断开或重连时触发

ZOO_NOTWATCHING_EVENT:watch移除事件,服务端出于某些原因不再为客户端watch节点时触发

watch事件与zookeeper读操作的对应关系图:

2 watcher api

Watcher是Zookeeper用来实现distribute lock, distribute configure, distribute queue等应用的主要手段。要监控data_tree上的任何节点的变化(节点本身的增加,删除,数据修改,以及孩子的变化)都可以在获取该数据时注册一个Watcher,这有很像Listener模式。一旦该节点数据变化,Follower会发送一个notification response,client收到notification响应,则会查找对应的Watcher并回调他们。
有以下接口可以注册Watcher:

1. Stat exists(final String path, Watcher watcher)

2. Stat exists(String path, boolean watch)

3. void exists(String path, boolean watch, StatCallback cb, Object ctx)

4. void exists(final String path, Watcher watcher, StatCallback cb, Object ctx)

5. byte[] getData(final String path, Watcher watcher, Stat stat)

6. byte[] getData(String path, boolean watch, Stat stat)

7. void getData(final String path, Watcher watcher, DataCallback cb, Object ctx)

8. void getData(String path, boolean watch, DataCallback cb, Object ctx)

9. List<string> getChildren(final String path, Watcher watcher)

10. List<string> getChildren(String path, boolean watch)

11. void getChildren(final String path, Watcher watcher,ChildrenCallback cb, Object ctx)

如果参数需要传递watcher,则可以自己定义Watcher进行回调处理。如果是Boolean型变量,当为true时,则使用系统默认的Watcher,系统默认的Watcher是在zookeeper的构造函数中传递的Watcher。如果Watcher为空或者Boolean变量时为false,则表明不注册Watcher。如果获取数据后不需要关注该数据是否变化,就不需要注册Watcher。上面没有返回值的都是异步调用模式。需要注意的是,一旦Watcher被调用后,将会从map中删除,如果还需要关注数据的变化,需要再次注册。
Watcher原理 要搞清楚Watcher的原理,让我们看看Watcher的工作流程。

Watcher的使用与注意事项

Watcher需要每次都要注册。

并不是Watcher的节点被修改n次,客户端注册就会被通知n次。如果watcher的节点频繁被修改,有可能修改了10次,客户端被通知8次。如果client与server连接状态发生改变,watcher总是会被通知。

3 一个例子

  1. #include <string.h>
  2. #include <errno.h>
  3.  
  4. #include "zookeeper.h"
  5.  
  6. static zhandle_t *zh;
  7.  
  8. /**
  9. * In this example this method gets the cert for your
  10. * environment -- you must provide
  11. */
  12. char *foo_get_cert_once(char* id) { return 0; }
  13.  
  14. /** Watcher function -- empty for this example, not something you should
  15. * do in real code */
  16. void watcher(zhandle_t *zzh, int type, int state, const char *path,
  17. void *watcherCtx) {}
  18.  
  19. int main(int argc, char argv) {
  20. char buffer[512];
  21. char p[2048];
  22. char *cert=0;
  23. char appId[64];
  24.  
  25. strcpy(appId, "example.foo_test");
  26. cert = foo_get_cert_once(appId);
  27. if(cert!=0) {
  28. fprintf(stderr,
  29. "Certificate for appid [%s] is [%s]\n",appId,cert);
  30. strncpy(p,cert, sizeof(p)-1);
  31. free(cert);
  32. } else {
  33. fprintf(stderr, "Certificate for appid [%s] not found\n",appId);
  34. strcpy(p, "dummy");
  35. }
  36.  
  37. zoo_set_debug_level(ZOO_LOG_LEVEL_DEBUG);
  38.  
  39. zh = zookeeper_init("localhost:3181", watcher, 10000, 0, 0, 0);
  40. if (!zh) {
  41. return errno;
  42. }
  43. if(zoo_add_auth(zh,"foo",p,strlen(p),0,0)!=ZOK)
  44. return 2;
  45.  
  46. struct ACL CREATE_ONLY_ACL[] = {{ZOO_PERM_CREATE, ZOO_AUTH_IDS}};
  47. struct ACL_vector CREATE_ONLY = {1, CREATE_ONLY_ACL};
  48. int rc = zoo_create(zh,"/xyz","value", 5, &CREATE_ONLY, ZOO_EPHEMERAL,
  49. buffer, sizeof(buffer)-1);
  50.  
  51. /** this operation will fail with a ZNOAUTH error */
  52. int buflen= sizeof(buffer);
  53. struct Stat stat;
  54. rc = zoo_get(zh, "/xyz", 0, buffer, &buflen, &stat);
  55. if (rc) {
  56. fprintf(stderr, "Error %d for %s\n", rc, __LINE__);
  57. }
  58.  
  59. zookeeper_close(zh);
  60. return 0;
  61. }

转自:http://zoutm.iteye.com/blog/708468

zookeeper系列之异步通知模式-Watcher的更多相关文章

  1. zookeeper系列之:独立模式部署zookeeper服务

    一.简述 独立模式是部署zookeeper服务的三种模式中最简单和最基础的模式,只需一台机器即可,独立模式仅适用于学习,开发和生产都不建议使用独立模式.本文介绍以独立模式部署zookeeper服务器的 ...

  2. Linux通信之异步通知模式

    [参考]韦东山 教学笔记 为了使设备支持异步通知机制,驱动程序中涉及以下3项工作:1. 支持F_SETOWN命令,能在这个控制命令处理中设置filp->f_owner为对应进程ID. 不过此项工 ...

  3. arm驱动linux异步通知与异步IO【转】

    转自:http://blog.csdn.net/chinazhangzhong123/article/details/51638793 <[ arm驱动] linux异步通知与 异步IO> ...

  4. Smart20学习记录----异步通知

    异步通知: 阻塞与非阻塞访问.poll()函数提供了较好地解决设备访问的机制(应用程序主动访问) 异步通知:一旦设备就绪,则主动通知应用程序,这样应用程序根本就不需要查询设备状态,这一点非常类似于硬件 ...

  5. linux异步通知

    简述 linux下异步方式有两种:异步通知和异步IO(AIO),aio请参考:linux异步IO--aio 异步通知的含义是:一旦设备就绪,则主动通知应用程序,这样应用程序就不需要查询设备状态,准确称 ...

  6. Linux内核开发之异步通知与异步I/O(一)

    “小王,听说过锦上添花吧..”我拍拍下王的头说. “还锦上添花你,为你上次提的几个东东,我是头上长包..”小王气愤地瞪着我. “啊,为啥这样呢,本来还特意拒绝了MM的月份,抽出时间打算给你说点高级的东 ...

  7. 异步通知与异步I/O

    异步通知:很简单,一旦设备准备好,就主动通知应用程序,这种情况下应用程序就不需要查询设备状态,这是不是特像硬件上常提的"中断的概念".上边比较准确的说法其实应该叫做"信号 ...

  8. 关于 exynos 4412 按键中断 异步通知

    以下是驱动测试代码: //内核的驱动代码 #include <linux/init.h> #include <linux/module.h> //for module_init ...

  9. linux 设备驱动与应用程序异步通知

    一.异步通知机制简介 异步通知机制的意思:一旦设备准备就绪,可以主动的通知应用程序进行相应的操作,从而使得应用程序不必去查询设备的状态. 异步通知比较准确的称谓是"信号驱动的异步IO&quo ...

随机推荐

  1. SharePoint 2010 Modal Dialog

    SharePoint 2010 Modal Dialog Tweet   Modal dialog play very important role to improve the user exper ...

  2. 用tomcat6自定义域名

    第一步:tomcat配置 修改server.xml文件 8080端口 更改为 80端口 并在<Host name="localhost"  appBase="web ...

  3. Qt之Windows开发移植问题汇总

    来源:http://blog.sina.com.cn/s/blog_a6fb6cc90101auw6.html 在用Qt开发完成项目后,就需要将其打包并且移植在其他机器上,能在其他PC机上正常跑起来才 ...

  4. Python 模块功能paramiko SSH 远程执行及远程下载

    模块 paramiko paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现 ...

  5. android cordova h5总结

    最近项目 替换页面  把80%页面替换成h5了. 首页h5页面可以放在android本地.增加访问速度.节省用户流量 把服务器上的  js代码 压缩成zip格式  放在asset目录.当应用安装时候 ...

  6. JS-将input输入框写入的小写字母全部转换成为大写字母的JS代码

    <input name="htmer" type="text" onkeyup="this.value=this.value.toUpperCa ...

  7. Spring Boot 系列教程6-全局异常处理

    @ControllerAdvice源码 package org.springframework.web.bind.annotation; import java.lang.annotation.Ann ...

  8. java vector 和ArrayList的区别

    相同点: 1.都是使用数组存储数据 不同点: 1.Vector是显示安全的,ArrayList是线程不安全的 Vector部分代码: public synchronized boolean add(E ...

  9. 用for、while、do-while循环输出10句“好好学习,天天向上!”

    #include "stdio.h" void main() { int time; ;time<=;time++) printf("%d.好好学习,天天向上!\n ...

  10. Python CGI编程和CGIHTTPServer

    Python2.7 的CGIHTTPServer 可以作为一个简单的HTTP服务器,能够调用cgi脚本 1 在任意目录下创建一个特殊的目录 cgi-bin ,用于存放自己写的脚本(.py或.cgi) ...