一、什么是Watcher机制
Zookeeper可以理解为是一种提供持久化功能的内存树状结构存储,树的每一个节点被称为znode,当一个zonde节点执行了更新操作,我们称之为事件,而一个监视点表示一个与之关联的znode节点和事件类型组成的一个单次触发器,当一个监视点被一个事件触发时,就会产生一个通知,通知是注册了监视点的应用客户端收到事件的报告信息。当客户端注册了一个监视点来接收通知,匹配该监视点条件的第一个事件会触发监视点的通知并且最多只触发一次。Watcher机制采用Push/Pull的方式进行数据的更新,当zonde发生变化时,ZK服务器会产生一个WatchedEvent事件通知客户端(Push),客户端根据事件类型从ZK服务器获取数据进行下一步的处理(Pull)。
二、Watcher的类文件结构
Watcher在Zookeeper中是一个接口,客户端根据自己的需要实现该接口并设置Watcher。下图是该接口的类文件UML
1、Zookeeper状态
- Disconnected:客户端是断开连接的状态,不能连接服务集合中的任意一个
- SyncConnected:客户端是连接状态,连接其中的一个服务
- AuthFailed:鉴权失败
- ConnectedReadOnly:客户端连接只读的服务器
- SaslAuthenticated:SASL认证
- Expired:服务器已经过期了该客户端的Session
2、Zookeeper事件类型
- None:无
- NodeCreated:节点创建
- NodeDeleted:节点删除
- NodeDataChanged:节点数据改变
- NodeChildrenChanged:子节点改变(添加/删除)
三、设置Watcher
Watcher是由一系列读取操作所设置的一次性触发器,每一个Watcher由一个特定的操作触发。这些操作主要包括:
- getData:获取数据
- exists:节点是否存在
- getChildren:获取子节点
当客户端进行这些操作,或者在创建Zookeeper客户端时,可以显式的设置一个Watcher。在Zookeeper客户端,与服务器的连接通过一个ClientCnxn对象进行维护,ClientCnxn中通过ClientWatchManager去管理客户端注册的Watcher,当进行上述操作时,客户端会将ClientWatchManager维护的Watcher同步给ZK服务器
void primeConnection() throws IOException {
LOG.info("Socket connection established to "
+ clientCnxnSocket.getRemoteSocketAddress()
+ ", initiating session");
isFirstConnect = false;
long sessId = (seenRwServerBefore) ? sessionId : 0;
ConnectRequest conReq = new ConnectRequest(0, lastZxid,
sessionTimeout, sessId, sessionPasswd);
synchronized (outgoingQueue) {
// We add backwards since we are pushing into the front
// Only send if there's a pending watch
// TODO: here we have the only remaining use of zooKeeper in
// this class. It's to be eliminated!
//获取Zookeeper客户端注册的Watcher并设置到待发送Packet中
if (!disableAutoWatchReset) {
List<String> dataWatch