一,Zookeeper客户端的主要组件
Zookeeper客户端主要由以下几个核心部分组成:
1,Zookeeper实例:客户端入口。
通过调用Zookeeper构造方法生成客户端实例。
2,ClientWatchManager:客户端Watcher管理器。
3,HostProvider:客户端地址列表管理器。
4,ClientCnxn:客户端核心线程。内部又包含2个线程,SendThread和EventThread。SendThread是一个IO线程,主要负责Zookeeper客户端与服务端的网络通信。EventThread是一个事件线程,主要负责对服务端事件进行处理。
二,Zookeeper客户端的启动流程
首先看一下Zookeeper构造方法
Zookeeper(String connectString, int sessionTimeout, Watcher watcher, boolean canBeReadOnly)
初始化阶段
1,设置默认Watcher。
如果在Zookeeper的构造方法中传入一个Watcher对象的话,Zookeeper会将这个对象保存在ZKWatcherManager的defaultWatcher中,作为整个客户端会话期间的默认watcher。
2,设置Zookeeper服务器地址列表。
对于传入的服务器地址,客户端会将其保存在服务器地址列表管理器HostProvider中。
3,创建ClientCnxn。
Zookeeper客户端首先会创建一个网络连接器ClientCnxn,用来管理客户端与服务端的网络通信。
4,初始化SendThread和EventThread。
SendThread是一个IO线程,主要负责Zookeeper客户端与服务端的网络通信。EventThread是一个事件线程,主要负责对服务端事件进行处理。
会话创建阶段
5,启动SendThread和EventThread。
SendThread首先会判断当前客户端的状态,进行一系列清理工作,为客户端发送会话创建请求做准备。
6,获取一个服务器地址。
在开始创建TCP连接之前,SendThread首先需要获取一个Zookeeper服务器的地址,这通常是从HostProvider中随机获取一个地址,然后委托给ClientCnxnSocket去创建与Zookeeper服务端的TCP连接。
7,创建TCP连接。
获取到服务器地址后,ClientCnxnSocket负责和服务端创建一个TCP长连接。
8,构造ConnectRequest请求。
SendThread根据当前客户端的实际设置,构造一个ConnectRequest请求,该请求代表了客户端试图与服务端创建一个会话。同时,Zookeeper客户端还会进一步将该请求包装成网络IO层的Packet对象,放入请求发送队列outgoingQueue中。
9,发送请求。
ClientCnxnSocket从outgoingQueue取出一个待发送的Packet对象,将其序列化成ByteBuffer后,向服务端进行发送。
响应处理阶段
10,接收服务端响应
ClientCnxnSocket接收到服务端的响应后,会先判断当前的客户端状态是否是已初始化状态。如果尚未完成初始化,那么就认为该响应一定是会话创建请求的响应,直接交给readConnectResult方法来处理该响应。
11,处理response
ClientCnxnSocket会对接收到的服务端响应进行反序列化,得到ConnectResponse对象,并从中获取到Zookeeper服务端分配的会话sessionId。
12,连接成功。
连接成功后,一方面需要通知SendThread线程,进一步对客户端进行会话参数的设置,包括readTimeout和connectTimeout等,并更新客户端状态。另一方面,需要通知地址管理器HostProvider当前成功连接的服务器地址。
13,生成事件,SyncConnected-None。
为了能够让上层应用感知到会话的成功创建,SendThread会生成一个事件SyncConnected-None,代表客户端与服务端创建会话成功。并将该事件传递给EventThread。
14,查询watcher
EventThread收到事件后,会从ClientWatchManager管理器查询出对应的watcher,针对SyncConnected-None事件,找出步骤2中存储的默认的watcher,然后放到EventThread的waitingEvents队列中。
15,处理事件。
EventThread不断从waitingEvents队列中取出待处理的watcher,然后直接调用该对象的process接口方法,以达到触发watcher的目的。