本文主要继续上文中对数据模型的概述部分,继续深入探讨zk中的监听机制
上文回顾
在上文中,我们简单总结一下一个zk中的的监听器接口类Watcher主要由以下几个部分构成
* 通知状态 Watcher.Event.Keeperstate
* 事件类型 Watcher.Event.EventType
* 监听器类型 Watcher.Event.WatcherType
* 处理事件通知的方法 process(WatchedEvent event)
WatchedEvent event对象表示一个监听事件,从源码中可以看出一个监听事件主要由以下几个部分组成
* String path:监听器注册的节点路径
* Watcher.Event.Keeperstate keeperState
* Watcher.Event.WatcherType eventType
注册监听器的方法
- ZooKeeper构造器
- getData()
- getChildren()
- exsits()
ZooKeeper构造器中设置默认监听器的过程
这也是客户端与服务端一次会话创建的过程
public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
boolean canBeReadOnly, HostProvider aHostProvider, ZKClientConfig clientConfig) throws IOException {
if (clientConfig == null) {
clientConfig = new ZKClientConfig();
}
this.clientConfig = clientConfig;
watchManager = defaultWatchManager();
watchManager.defaultWatcher = watcher;
ConnectStringParser connectStringParser = new ConnectStringParser(
connectString);
hostProvider = aHostProvider;
cnxn = new ClientCnxn(connectStringParser.getChrootPath(),
hostProvider, sessionTimeout, this, watchManager,
getClientCnxnSocket(), canBeReadOnly);
cnxn.start();
}
执行流程
- 将watcher对象传入到zk的构造器中
- 将watcher对象保存在ZooKeeper中的ZKWatchManager的defaultWatcher中
- ZKWatchManager对象被传入到ClientCnxn构造器中(watcher对象保存在ZKWatchManager中)
- 到上面这步,watcher对象已经被传递到了ClientCnxn中
- 执行cnxn.start(),这时候会执行sendThread.start()和eventThread.start()
- 执行sendThread.start()
- 在sendThread.start()中,从hostProvider随机获取一个服务器地址,建立连接
- 建立连接的过程实在sendThread的startConnect()方法中完成的,最终会调用clientCnxnSocket.connect(addr)
- clientCnxnSocket是一个抽象类,connect(addr)方法会调用其子类的重载方法。常见的子类有:ClientCnxnSocketNIO和ClientCnxnSocketNetty
- ClientCnxnSocketNIO中的connect(addr), 在该方法中采用NIO的方式建立TCP连接(selector)
- tcp连接建立之后,调用sendThread的primeConnection()方法创建与服务端的会话
- 在primeConnection()方法中,构造出一个ConnectRequest对象,然后这个对象会被传入packet对象中,放入ClientCnxn的outgoingQueue中等待发送
- 最后调用clientCnxnSocket.connectionPrimed()对通道注册感兴趣的事件