Zookeeper 提供的了分布式数据的公布/订阅功能,通过 Watch 机制来实现这样的分布式的通知功能。


Zookeeper 同意client向server注冊一个Watch监听。当服务端的一些指定的事件触发了这个Watch 。就会向指定的client发送一个事件通知来实现分布式通知。
整个Watch的注冊和通知过程如图:
Zookeeper的 Watcher 机制主要包含client现成、client WatchManager、Zookeeperserver三部分,详细流程是:client 向Zookeeper注冊的同一时候。把Watcher对象存储在client的WatchManager中,当Zookeeperserver端触发Watcher事件后,会向client发送通知。client线程从WatchManager中取出相应的Watcher对象运行回掉逻辑。

client注冊Watcher
可用在创建一个client实例时,向构造方法中传入一个默认的Watcher对象,也能够在调用 getData() , getChildren() , exist() 三个接口向 Zookeeper server注冊Watcher。不管使用哪种方式注冊。原理都是一致的。 这里已 getData接口说明:

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

在向 getData 接口注冊 Watcher 后。client首先会对当前client请求 request 进行标记。将其置为“使用 Watcher监听”,同一时候会封装一个 Watcher 的注冊对象 WatcherRegistration 对象。用于临时保存数据节点路径和Watcher的相应关系。详细逻辑代码:

public Stat getData(final String path, Watcher watcher , Stat stat){
     ..........
     WatcherRegistration wrt = null ;
     if(watcher !=null){
          wrt = new DataWatchRegistration(watcher,path);
     }
     ......
     request.setWatche(watcher!=null) ;//------注意此处兴许会用到
     ReplyHeader r = cnxn.submitRequest(h,request,response,wrt);

在Zookeeper中,Packet 能够被看做是一个最小的通信协议单元。用于client和server端之间进行网络传输,不论什么一个须要传输的对象都要被包装成 Packet 对象进行传输。由于 ClientCnxn 中的 WatcherRegistration 又会被封装到 Packet 中去,然后放入发送队列中等待client发送。

Packet queuePacket(RequestHeader h , ReplyHeader r , Record reqest , Record response, AsyncCallback cb ,String clientPath , String serverPath , Object ctx , WatcherRegistration wrt){
     .......
     synchronized(outgoingqueue){
          packet = new Packet(h,r,request,response,wrt) ;
          .........
          outgoingqueue.add(packet);
     }
....
}

随后,Zookeeper client会向服务端发送这个请求,同一时候等待服务端的返回。完毕请求发送后,会由client SendThread 线程的 readResponse 方法接受来自服务端的响应。finishPacket 方法会从 Packet 中取出相应的 Watcher 并注冊到ZkManager中去,代码逻辑:
     
private void finishPacket(Packet p){
     if(p.watcherRegistration != null){
          p.watcherRegistration.register(p.replyHeader.getErr());
     }
.......
}

如今把 Watcher 对象从 WatchRegistration 对象中取出来:
     
protected Map<String,HashSet<Watcher>> getWatchers(int rc){
     
     return watchManager.dataWatches ;

}

public void register(int rc){
     if(shouldAddWatch(rc)){
          Map<String,HashSet<Watcher>> watches = getWatchers(rc) ;
  synchronized(watches){
     
     Set<Watcher> watchers = watches.get(clientPath) ;
     if(watchers ==null){
            watchers  =new HashSet<Watcher>();
            watches.put(clientPath,watchers);
   }
             watchers.add(watcher);
     .........
}
在上面的register 方法中会吧临时存放的 watcher 对象转交给 ZKWatcherManager , 并终于保存到dataWatchers 中 ,dataWatchers , ZKWatcherManager 都是 Map<String,Set<Watcher>> 类型的数据结构,用于把数据节点的路径和Watcher对象一一映射后保存起来。

   

在上面的流程中,WatcherRegistration 在底层的网络序列化究竟层的字节数组中。















Watcher 实现机制之client注冊的更多相关文章

  1. 一个简单RPC框架是怎样炼成的(VI)——引入服务注冊机制

    开局篇我们说了.RPC框架的四个核心内容 RPC数据的传输. RPC消息 协议 RPC服务注冊 RPC消息处理 接下来处理RPC服务的注冊机制.所谓注冊机制,就是Server须要声明支持哪些rpc方法 ...

  2. Windows Azure Mobiles Services实现client的登录注冊

    下文仅仅是简单实现,client以Android端的实现为例: 用户表Account: package com.microsoft.ecodrive.model; public class Accou ...

  3. Eureka 的 Application Service client的注冊以及执行演示样例

            Eureka 服务器架起来了(关于架设步骤參考博客<Linux 下 Eureka 服务器的部署>),如今怎样把我们要负载均衡的服务器(也就是从 Application Cl ...

  4. 从注冊流程 分析怎样安全退出多个Activity 多种方式(附DEMO)

    前言 因为一个同学问到我怎样依照一个流程走好之后回到首页.我曾经看到过4个解决方式,后来发现有做个记录和总结的必要,就写了这篇博文. (之前看小强也写过一篇,这里通过自身的分析完整的总结一下下面6种方 ...

  5. Android应用程序注冊广播接收器(registerReceiver)的过程分析

    前面我们介绍了Android系统的广播机制,从本质来说,它是一种消息订阅/公布机制,因此,使用这样的消息驱动模型的第一步便是订阅消息:而对Android应用程序来说,订阅消息事实上就是注冊广播接收器, ...

  6. 基于Servlet、JSP、JDBC、MySQL的一个简单的用户注冊模块(附完整源代码)

    近期看老罗视频,做了一个简单的用户注冊系统.用户通过网页(JSP)输入用户名.真名和password,Servlet接收后通过JDBC将信息保存到MySQL中.尽管是个简单的不能再简单的东西,但麻雀虽 ...

  7. Android Binder分析二:Natvie Service的注冊

    这一章我们通过MediaPlayerService的注冊来说明怎样在Native层通过binder向ServiceManager注冊一个service,以及client怎样通过binder向Servi ...

  8. android binder 机制二(client和普通server)

    在讲它们之间的通信之前,我们先以MediaServer为例看看普通Server进程都在干些什么. int main() { -- // 获得ProcessState实例 sp<ProcessSt ...

  9. spring揭秘 读书笔记 二 BeanFactory的对象注冊与依赖绑定

    本文是王福强所著<<spring揭秘>>一书的读书笔记 我们前面就说过,Spring的IoC容器时一个IoC Service Provider,并且IoC Service Pr ...

随机推荐

  1. h5开发app,移动端 click 事件响应缓慢的解决方案

    造成点击缓慢的原因 从点击屏幕上的元素到触发元素的 click 事件,移动浏览器会有大约 300 毫秒的等待时间.为什么这么设计呢? 因为它想看看你是不是要进行双击(double tap)操作. 使用 ...

  2. S​Q​L​_​S​e​r​v​e​r​_​2​0​0​8​定​期​自​动​备​份​详​细​图​解

    S​Q​L​_​S​e​r​v​e​r​_​2​0​0​8​定​期​自​动​备​份​详​细​图​解 设置自动数据库的定期备份计划. http://wenku.baidu.com/link?url=Tu ...

  3. Autorelease pools 官方文档

    翻译自: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAu ...

  4. Ubuntu终端常用快捷键汇总

    Ubuntu终端常用的快捷键 - 转自- 博客园  http://www.cnblogs.com/nucdy/p/5251659.html   Ubuntu中的许多操作在终端(Terminal)中十分 ...

  5. centos6 磁盘与文件系统管理

    一.磁盘管理 磁盘构成 1.圆形磁盘 2.磁盘读取头 3.机械手臂 4.主轴马达 运作原理 数据存储在具有磁性物质的圆形磁盘上,读写操作主要是通过机械手臂上的磁盘读取头来达成,实际运作时,主轴马达让磁 ...

  6. 运维笔记:zabbix的运用(1)安装过程

    前言 如果是用了阿里云或者腾讯云,他们都有各种监控帮我们做好.但是如果是遇到了自己维护自己机房的服务器,那么一些可视化或者监控就很有意义了.监控可能有很多种方案,这里就以比较老牌通吃的zabbix来解 ...

  7. 将一个list中的元素的某一属性取出来单独放到一个list里面

    有很多时候我们会遇到这样的场景,就是要将一个list中的某一个元素中的某一属性单独拿出来放在一个新的list里面,这中时候,我们就可以用以下的方法来进行实现: List<DTO> item ...

  8. php使用trait遇到的一个问题

    php是单继承语言,也是就是一个类只能继承一个单独的原始类自PHP5.4.0起,PHP实现了一种代码复用的方法,称为Traittrait 是在一些类(Class)的应该具备的特定的属性或方法,而同父级 ...

  9. Quartz--01

    Quartz 调度器(scheduler):定时定频率的去执行任务 任务(job):业务逻辑 触发器(trigger):让任务生效的时间 JobDetail(包含任务实现类,任务信息) trigger ...

  10. Qt——信号与槽用法总结(未完待续)

    1.设计模式中信号与槽编辑选项卡 2.右键组件,转到槽,写函数 void LoginDialog::on_loginBtn_clicked() { accept(); } 3.信号与槽编辑模式 按下F ...