Zookeeper的watcher数据变更通知机制

在zookeeper中,引入了watcher机制来通知客户端,服务端的节点信息发生了变化。其允许客户端向服务端注册一个watcher监听,

当服务端的一些指定事件触发了这个watcher,就会向指定的客户端发送一个事件通知。


zookeeper的watcher机制主要包括客户端线程、客户端watchermanager和zookeeper服务器三部分。其具体工作流程为,

客户端在向zookeeper服务器注册watcher的同时,会将watcher对象存储在客户端的watchermanager中。当服务端触发watcher事件后,

会向客户端发送通知,客户端线程从watchermanager中取出对应的watcher对象,根据通知类型和节点路径,来处理回调逻辑,对客户端数据做出相应处理。


watch工作机制

zookeeper的工作机制主要包括三个步骤:客户端注册watcher、服务端处理watcher和客户端回调watcher事件。


首先需要了解一下zookeeper中的watchedevent结构,其包括三个基本属性:通知状态(keepstate)、事件类型(eventType)和节点路径(path)。

zookeeper使用watchedevent对象来封装服务端事件并传递给watcher,而实际传递的是watcherevent,其结构和watchedevent一样,

只是其实现了序列化,可以在网络上传输。从这里可以看出,watcher事件只是一个简单的事件说明,并不包含事件的数据变更内容,

这样能保证网络传输的高效性。


客户端注册watcher

在通过客户端接口调用时,可以指定一个watcher接口,以接受服务器事件的回调。在注册watcher即可后,客户端首先会对当前客户端请求request进行标记,

将其设置为“使用watcher监听”,同时会封装一个watcher的注册信息watchregistration对象,用于暂时保存数据数据节点和watcher的对象关系。

由于zookeeper中的最小通讯单元为packet,因此,在clientCnxn中watchregistration又会被封装到Packet中,然后放入发送队列中等待客户端发送。随后,

客户端会想服务端发送请求,并等待请求返回。完成请求之后,客户端的SendThread线程的readresponse方法负责接收服务端的请求,

并将接收到的packet中的watcher注册到ZKWatcherManager中,并最终保存到dataWatchers中,用于服务端事件的回调的时候获取对应节点的对应watcher事件。


服务端处理watcher

从上面的分析,我们可以知道,客户端注册的watcher并不会传递到服务端,只是在客户端进行了watcher的保存,所以服务端接受到watch注册事件之后,

需要将该事件进行封装,在服务端也进行保存。

ServerCnxn存储

我们知道ServerCnxn是服务端与客户端进行网络交互的一个接口,代表了客户端与服务端的连接。其底层采用netty实现。所以,在接受到注册请求之后,服务端会将ServerCnxn对象和数据阶段路径保存到WatchManager的watchTable和watch2Paths中。方便事件触发时的调用。

watcher触发

在对指定的节点发生相关的事件时,通过调用WatchManager的triggerWatch方法触发相关的事件。其通过将节点信息和事件类型进行封装成为watchedevent,

并查找到到对应节点的注册的watcher,然后分别调用watcher的回调函数process。而在process函数中其实就是通过封装的ServerCnxn

向客户端发送watchedevent数据请求。具体的watcher业务处理则在客户端处理。

客户端回调watcher

上面我们分析了,服务端并不处理watcher事件的具体逻辑,只是将事件通知发送到客户端。下面分析客户端是如何处理服务端发送回来的事件通知的。

SendThread接收事件通知

SendThread是客户端开启的与服务端建立TCP长连接的线程,它会一直保持连接状态,采用心跳监测的方式确保与服务端的连接存活。

在客户端的SendThread中,当接收到服务端请求之后,会将请求反序列化成watchedevent对象,并将watchedevent对象转换为watcherevent对象,

最后将watcherevent对象添加到EventThread线程,完成对watcher的回调。


EventThread是客户端的一个专门处理watcher时间的线程,其保持了一个待处理事件的队列。它根据传递的事件的类型和节点信息,

从客户端的ZKWatcherManager中取出相关的watcher,将其添加到EventThread事件队列中,并在去run方法中不断取出watcher事件进行处理。


但是,这里需要注意一点就是,(1)事件注册是一次性的,因为在每次处理事件之后,就会将相应的watcher注册删除;(2)客户端接收到的服务端watcher事件中

并不包含事件更改的具体内容,只是告知发生了这样一个watcher事件,所以,客户端在接收到watcher事件之后,需要在回调函数process中对服务端的数据进行重新获取,

才能获得更改的具体内容。


  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值