二、序列化与协议
1、序列化
ZooKeeper中使用Jute进行数据的序列化与反序列化。
1)使用步骤:
(1)实体类需要实现Record接口的serialize和deserialize方法;
(2)构建序列化器OutputArchive;
(3)序列化:调用serialize方法;
(4)反序列化:调用deserialize方法。
2、通信协议
基于TCP/IP协议,ZooKeeper实现了自己的通信协议完成通信。
1)请求头RequestHeader中包含请求的最基本信息,包括xid、type。xid表示请求的先后顺序,type表示请求类型,包括:创建节点、删除节点、获取节点数据等。
2)请求体Request是请求的主体内容部分,包含请求的所有操作,不同的请求类型,请求体部分是不同的。
三、客户端
1、会话创建过程
1)初始化阶段
①初始化ZooKeeper对象:同时创建一个客户端的watcher管理器ClientWatchManager;
②设置会话默认watcher:如果构造方法中传入一个watcher对象,将这个对象作为默认的watcher保存在ClientWatcherManager中;
③构造ZooKeeper服务器地址列表管理器HostProvider:向其中传入服务器地址列表;
④创建并初始化客户端网络连接器ClientCnxn:用于管理客户端与服务端的网络连接,他有两个线程:SendThread和EventThread。SendThread用于用于客户端与服务端网络通信;EventThread用于服务端事件处理。
⑤初始化SendThread和EventThread
2)会话创建阶段
⑥启动SendThread和EventThread;
⑦获取服务器地址:SendThread从HostProvider中取出一个地址,交给ClientCnxnScocket,创建于ZooKeeper服务器之间的连接;
⑧创建TCP连接:
ClientCnxnScocket和服务器之间创建TCP连接;
⑨构造ConnectRequest请求:
SendThread构造出一个ConnectRequest请求,将该请求包装成Packet独享,放入请求发送队列outgoingQueue中;
⑩发送请求:
ClientCnxnScocket负责从outgoingQueue中取出一个待发送的Packet对象,序列化之后,向服务端发送
3)响应处理阶段
⑪接收服务端响应
⑫处理Response
ClientCnxnScocket将接收到的响应反序列化,得到ConnectResponse对象,并从中获得服务端分配的会话sessionId;
⑬连接成功
SendThread设置会话参数,更新客户端状态,通知HostProvider当前成功连接的服务器地址;
⑭生成事件
SendThread生成一个事件SyncConnected-None,并将该事件传递给EventThread线程;
⑮查询watcher:
EventThread线程收到事件后,从ClientWatchManager中查询出对应的Watcher,放入EventThread的waitingEvents队列中;
⑯处理事件:
EventThread不断地从waitingEvents队列中取出待处理的watcher对象,调用process方法,触发watcher。
2、服务器地址列表connectString参数
在使用ZooKeeper构造方法时,传入的服务器地址列表connectString参数是一个String字符串,客户端会将它先放入一个ConnectStringParser中封装起来,ConnectStringParser是一个服务器地址列表的解析器,对传入的connectString做两个处理:解析chrootPath;保存服务器地址列表。
1)Chroot:客户端隔离命名空间
ChrootPath特性允许每个客户端为自己设置一个命名空间,该客户端对服务器的任何操作,都将会被限制在自己的命名空间下。
2)HostProvider:地址列表管理器
ConnectStringParser解析器对服务器地址做一个简单处理,最后被封装到StaticHostProvider类中,StaticHostProvider先对这些地址逐个进行解析,放入集合保存起来,最后使用Collections的shuffle方法将服务器地址列表进行随机的打散。通过StaticHostProvider的next方法获取一个服务器地址。next方法中先将随机打散的服务器地址列表拼装成一个环形队列。
3、ClientCnxn:网络IO
ClientCnxn负责客户端与服务端之间的网络通信。
1)Packet
ClientCnxn内部定义的,ZooKeeper中请求与响应的载体。Packet中包含请求头、响应头、请求体、响应体、节点路径、注册的watcher。在网络传输的过程中,Packet的createBB方法只将请求头、请求体、readOnly三个属性进行序列化,其余属性不会进行网络传输。
2)outgoingQueue和pendingQueue队列
outgoingQueue是请求发送队列,专门用于存储需要发送到服务端的Packet集合。pendingQueue保存那些已经发送到服务端,但是需要等待服务端响应的Packet集合。
3)SendThread
维护了客户端与服务端的生命周期,实现心跳检测,自动重连;管理客户端所有的请求发送和响应接收操作;还负责将来自服务端的事件传递给EventThread。
4)EventThread
负责客户端的事件处理,并触发客户端注册的watcher监听。EventThread中有一个waitingEvents队列,临时存放需要被触发的watcher和回调器。