客户端可以在节点上注册监听器,当特定的事件发生后,zk会通知感兴趣的客户端。
我们在zkCli.sh客户端输入help命令,可以看到只有stat、ls、ls2、get四个命令可以增加watch事件。
我们想某个路径加监听器,ls path [watch],watch代表是否添加watch,1代表是的。
下面我们来看一下java源码。
zookeeper版本:
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.10</version>
</dependency>
那我们一般是怎么调用zookeeper的呢?首先定义一个Zookeeper对象
ZooKeeper zk = new ZooKeeper("199.198.956.901:2181", 5000, new ZKDemo());
多个IP用;隔开。其中 5000是session超时时间,new ZKDemo()是我们自定义的一个Watcher对象
public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, boolean canBeReadOnly) throws IOException {
this.watchManager = new ZooKeeper.ZKWatchManager();
LOG.info("Initiating client connection, connectString=" + connectString + " sessionTimeout=" + sessionTimeout + " watcher=" + watcher);
this.watchManager.defaultWatcher = watcher;
ConnectStringParser connectStringParser = new ConnectStringParser(connectString);
HostProvider hostProvider = new StaticHostProvider(connectStringParser.getServerAddresses());
this.cnxn = new ClientCnxn(connectStringParser.getChrootPath(), hostProvider, sessionTimeout, this, this.watchManager, getClientCnxnSocket(), canBeReadOnly);
this.cnxn.start();
}
在初始化zookeeper的时候,会new一个ZooKeeper.ZKWatchManager(),ZooKeeper.ZKWatchManager()是客户端watcher管理器,并把我们刚才传进来的new ZKDemo()赋值给this.watchManager.defaultWatcher,作为客户端watcherManager的默认watcher,这个默认watcher主要用来监听keeperState里面定义的各种链接状态转换事件,
/** @deprecated */
@Deprecated
Unknown(-1),
Disconnected(0),
/** @deprecated */
@Deprecated
NoSyncConnected(1),
SyncConnected(3),
AuthFailed(4),
ConnectedReadOnly(5),
SaslAuthenticated(6),
Expired(-112);
由客户端持有,伴随整个zookeeper生命周期,而不是一次触发即消亡。我们运行一下代码观察一下(IP和端口改成自己的):
public class ZKDemo implements Watcher {
private static final CountDownLatch cdl = new CountDownLatch(1);
public static void main(String[] args) throws IOException {
ZooKeeper zk = new ZooKeeper("199.198.956.901:2181", 5000, new ZKDemo());
System.out.println(zk.getState());
try {
cdl.await();
} ca