客户端是开发人员使用Zookeeper的主要的途径,以下内容将对Zookeeper的内部原理进行详细的学习和讲解。ZooKeeper的客户端主要有一下几个核心组件组成:
- ZooKeeper实例:客户端的入口,提供客户端访问ZooKeeper服务器的API。
- ClientWatchManager:客户端watcher管理器,负责管理客户端注册的Watcher。
- HostProvider:客户端地址列表管理器,管理的是连接的服务器的地址列表。
- ClientCnxn:客户端核心线程,其内部包含两个线程,即SendThread和EvnentThread。SendThread是一个IO线程,主要负责客户端和服务端之间的网络通信;EventThread是一个事件处理线程,主要负责对服务端事件进行处理。ClientCnxn类中,还有两个比较核心的队列outgoingQueue和pendingQueue,分别代表客户端的请求发送队列和服务器响应的等待队列。outgoingQueue存储的是那些需要发送到服务器端的Packet集合。pendingQueue存储的是那些从客户端发送到服务器的,但是需要等待服务器端响应的Packet集合。在EventThread中,也有一个waitEvents队列,用于临时存放需要被触发的Object,包括那些客户端注册的Watcher和异步接口中注册的回调器AsyncCallback。EventThread会不断的从waitingEvents这个队列中取出Object,识别出其具体类型Watcher或者AsyncCallback,并分别调用process和processResult接口方法来实现对事件的触发和回调。
客户端整体结构图如下
初始化阶段
ZooKeeper有四个构造方法,我们通过其中一个来进行分析
public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
boolean canBeReadOnly)
throws IOException
{
//默认watcher
watchManager.defaultWatcher = watcher;
//封装服务器地址列表,格式192.168.0.1:2181,192.168.0.2:2181
ConnectStringParser connectStringParser = new ConnectStringParser(connectString);
//将地址列表封装成List<InetSocketAddress>放到地址列表管理器中
HostProvider hostProvider = new StaticHostProvider(connectStringParser.getServerAddresses());
//创建客户端网络连接器ClientCnxn
cnxn = new ClientCnxn(connectStringParser.getChrootPath(),
hostProvider, sessionTimeout, this, watchManager,
getClientCnxnSocket(), canBeReadOnly);
//启动连接器,start()方法里是启动连接器的SendThread、EventThread两个线程
cnxn.start();
}
会话创建阶段
ClientCnxn的两个线程SendThread、EventThread启动起来之后,就进入了会话创建阶段