zookeeper watcher功能分析

getData,getChildren(),exists()这三个方法可以针对参数中的path设置watcher,当path对应的Node 有相应变化时,server端会给对应的设置了watcher的client  发送一个一次性的触发通知事件。客户端在收到这个触发通知事件后,可以根据自己的业务逻辑进行相应地处理。

注意这个watcher的功能是一次性的,如果还想继续得到watcher通知,在处理完事件后,要重新register。

1. 客户端




整个类设计可以分为三大类:

1)黄色部分表示处理Watcher功能
2)绿色部分表示nio处理中一个数据结构的封装
3)蓝色部分表示通过nio请求,接收数据的处理类


 

请求的处理流程:

  下面以 public byte[] getData(final String path, Watcher watcher, Stat stat) 接口为例进行说明:

      1. 在有Watcher的情况下,

      对照右上图的类图,把watcher,path包装成一个DataWatchRegistration对象。整个WatchRegistration的结 构主要是利用了继承的多态性,不同子类的getWatches方法返回不同的结果集,而这些对调用方是屏蔽的。

  2. 构造请求头

          不同方法请求头的主要区别是type不一样 

  3. 构造request,reponse

       从类图中也可以看出,不同的方法对象于不同的request,response对象,对getData方法来说,是对应于 GetDataRequestGetDataResponse

     GetDataRequest对象中的属性是:path,以及一个boolean watch用来表示这个请求是否有watch

  4. 构造响应头

        这时候,ReplyHeader还是一个空对象,这里的内容要等nio返回内容时进行填充。

5. 构造 Packet对象

       包含:RequestHeaderReplyHeaderrequest,response, watchRegistration

      在这里把 requestHeader,request对象进行序列化,放入packet对象的Bytebuffer 属性中。

     replyHeader,response对象目前都是空,内容要等nio返回内容,解释出Bytebuffer中内容进行填充。

      同时在一开始就构造的DataWatchRegistration对象赋值给packet对象中的watchRegistration属性,这属性会在收 packet对象时有作用,下面再介绍。

6. packet对象准备好后,把整个对象放入一个outgoingQueue LinkedList中,就等着通过niopacket对象中byteBuffer中的内容 发送给server端面。之所以使用LinkedList,是因为它提供了操作头,尾的方法。

7. packet被放入outgoingQueue中,等待SendThreadpacket对应的内容发送给server

8.如果是带callback的异步调用,则整个调用过程就结束,如果是同步调用的话,判断packetfinished状态是否为true,如果为false,进行wait,等待nio得到response后,把packet的状态改成finishedtrue,调用notify通知当前等待。

    后续NIO操作,server进行数据传输就交给专门的SendThread来处理。

   整个nio主要是是围绕SelectorSocketChannelSelectionKey,ByteBuffer这四个对象进行操作。

  在这里围绕主流程来描述:

    1. SelectionKey  处于isWritable状态时

       A outgoingQueue 中取出一个packet中的byteBuffer内容,写入socketChannel

       B outgoingQueue remove 第一个packet,

      C 如果这个packet对应的头不是ping, auth类型,把这个packet放入pendingQueue。因为这两个请求的返回不需要额外处理,因此也就不需要放在等待返回的对列中。   pendingQueue的作用就是:因为采用了NIO返回是异步的,当结果返回时,要能找到原来请求的对象,所以要维护这么一个列队来保存已经被发送, 但还没收到返回的Packet对象。

 

响应的流程分析

   响应的数据类型:

    sendthread接收来自serverresponse类型:

1)针对心跳的ping请求的resp

2)针对auth请求的resp

3)一般接口请求的resp

4)如果接口请求要求了watcher,当watcher关注的内容有变化时的notification

 

一般接口请求的resp处理:

1)  判断从ByteBuffer中反序列化出来的replyHeader中的xid和 pendingQueue中第一个packet维护的xid是否相同。Zookeeper是保证发发送的packet会发收到response,在这里是对这个有序性进行验证。

2)  反序列化出 response对象的内容。

3)  这个时候已经拿到了packet的响应内容,但为了对callback,watcher功能的支持,还需要额外的处理:

4)  A:如果这个packet包含了watcher,将这个请求对象的watcher注册到watcherManager,这是为了当针对watcher的notification响应到达的时候,能找到对应的watcher。

5)  B: 如果接口是同步调用的话,这时设置packet的finished为ture,并且通过notify进行通知。

6)  C: 如果是带callback的异步调用,则将packet放入eventThread,让eventThread异步调用callback接口。

 

针对watcher对应notification 的resp处理

如果sendthread分析出当前的response是针对watcher的notification,

1)  将reponse反序列化成WatcherEvent

2)  WatcherEvent转化成WatchedEvent

3)  之前说过如果请求带watcher,在返回时,会在watcherManager中注册对应的watcher。当收到WatchedEvent后,就可以根据event的数据从watcherManger中取到对应的watcher集合。

4)  将WatchedEvent和对应的watcher集合封装成WatcherSetEventPair

5)  WatcherSetEventPair放入eventThread中的waitingEvents列表

6)  eventthread在run循环中,取中WatcherSetEventPair,调用其中的watcher接口。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值