相关类
Watcher 接口
任何一个事件处理类都必须实现Watcher 接口,它有一个内部接口 Event,以及 process方法。前者定义了ZK的状态和事件类型的枚举,后者则定义了事件的回调方法。
@InterfaceAudience.Public
public interface Watcher {
@InterfaceAudience.Public
public interface Event {
@InterfaceAudience.Public
public enum KeeperState {
/*...*/}
@InterfaceAudience.Public
public enum EventType {
/*...*/}
}
abstract public void process(WatchedEvent event);
}
回调方法 process只有一个参数 WatchedEvent,这个类也很简单,只有三个参数,分别是通知状态、事件类型,以及节点路径。
public class WatchedEvent {
final private KeeperState keeperState;
final private EventType eventType;
private String path;
/*...*/
}
和 WatchedEvent 紧密相关的还有 WatcherEvent,两者都是对ZK服务端事件的封装,不过后者实现了序列化接口,可用于网络传输。
ZK服务端会将 WatchedEvent 包装成 WatcherEvent进行传输,客户端则需逆向处理,解包装成WatchedEvent来处理事件。
可以看到,WatchedEvent 和 WatcherEvent 都只有简单的事件本身的信息,而不包含具体的内容,因此需要客户端主动去获取感兴趣的最新数据。
工作机制
客户端注册
客户端可以通过 getData()、getChildren()和exist()三个接口来向服务端注册 Watcher。注册的原理都是相同的,这里仅以 getData() 为例进行分析。
getData 有两个重载方法,区别在于第二个参数。
// 使用自定义的 watcher
public byte[] getData(final String path, Watcher watcher, Stat stat)
// 是否使用默认的 watcher
public byte[] getData(String path, boolean watch, Stat stat)
默认的 watcher 在实例化 ZooKeeper 的时候指定:
public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher)
ZooKeeper 实例维护了一个 ZKWatchManager 类的实例,该类实现了ClientWatchManager接口,是客户端的 watcher 管理器。
默认 watcher 就保存在 ZKWatchManager 的 defaultWatcher 中。
private final ZKWatchManager watchManager = new ZKWatchManager();
private static class ZKWatchManager implements ClientWatchManager {
private final Map<String, Set<Watcher>> dataWatches =
new HashMap<String, Set<Watcher>>();
private final Map<String, Set<Watcher>> existWatches =
new HashMap<String, Set<Watcher>>();
private final Map<String, Set<Watcher>> childWatches =
new HashMap<String, Set<Watcher>>();
private volatile Watcher defaultWatcher;
/* ... */
}
回到getData,传递 watcher 参数后,首先会被封装成 WatchRegistration 对象,并设置 request 对象为“使用watcher监听”:
public byte[] getData(final String path, Watcher watcher, Stat stat)
throws KeeperException, InterruptedException {
/* ... */
WatchRegistration wcb = null;
if (watcher != null) {
wcb = new DataWatchRegistration(watcher, clientPath);
}
/* ... */
request.setWatch(watcher != null);
ReplyHeader r = cnxn.submitRequest(h, request, response, wcb);
/* ... */
}
然后在客户端连接对象cnxn(ClientCnxn)的 submitRequest()方法中,又被封装成 Packet 对象进行网络传输。
ZK源码解析:Watcher机制详解

本文详细介绍了Zookeeper的Watcher机制,从相关类如Watcher接口、WatchEvent和WatchedEvent,到客户端注册Watcher、服务端处理及客户端回调的过程。Watcher在客户端和服务器端都是一次性的,并且客户端回调是串行执行,保持轻量级通信,不包含具体数据,仅通知事件发生。
最低0.47元/天 解锁文章
7781

被折叠的 条评论
为什么被折叠?



