Zookeeper监听器
- 2019 年 11 月 1 日
- 筆記
Zookeeper提供了分布式数据的发布/订阅功能,可以让客户端订阅某个Znode,当Znode发生变化时,可以通知所有的订阅者。这个实现机制在Zookeeper里面就是Watcher机制。
Watcher机制本质就是客户端在服务端注册事件监听器,当服务端变化时,通知客户端。
通常Zookeeper客户端向服务端注册的监听器分为两种:
1、监听节点数据的变化;
2、监听子节点数量的变化;
对于监听器的实现来说,Zookeeper使用监听器事件来对应不同的监听器处理,包括:
- NodeCreated(节点创建)
- NodeDeleted(节点删除)
- NodeDataChanged(节点数据修改)
- NodeChildrenChanged(子节点修改)
除了事件状态,还包括对应的客户端连接的状态:
- Disconneced(连接失败)
- KeeperState:SyncConnected(连接成功)
- KeeperState:AuthFailed(认证失败)
- KeeperState:Expired(会话过期)
监听器工作流程:
1、客户端注册:
客户端通过getData、getChild、exist方法,向Zookeeper注册,然后将注册信息,保存到客户端的ZKWatchManager中。然后,将数据封装成Packet,通过ClientCnxn的SendThread将数据发送到服务端;
服务端会将注册信息存储在WatchManager中。
2、服务端通知:
当服务端发生变化时,会封装一个WatchEvent包括:通知状态、事件类型(也就是客户端连接状态)、节点路径,通过ServerCnxn发送给客户端,客户端ClientCnxn的EventThread会将通知存储到阻塞队列中,并移除客户端的存储,也就是ZKWatchManager中的数据。
3、客户端回调:
客户端ClientCnxn的EventThread会从阻塞队列中取出监听通知事件,调用对应的Watcher的process方法,完成客户端回调处理逻辑。

另外,Zookeeper监听器有几个特点:
一次性注册,也就是一旦一个Watcher被触发,Zookeeper就会移除响应的监听,所以,开发人员需要对监听的节点进行循环注册。但,循环注册适用于服务端的变化不频繁的场景,如果服务端的节点存在频繁的变化的情况,可能会存在监听丢失的情况。所以,需要做一些改变,使用监听器加主动获取数据相结合的方式,即,注册监听器之前主动获取服务端数据;触发监听之后,再主动获取服务端数据。
轻量级,服务端通知客户端的最小单位是WatchEvent,只包括通知状态、事件类型和节点路径,客户端向服务端注册也是尽量减小数据单元,这样设计的数据量和一次性的注册,使Zookeeper的内存和网络的开销都很小。