【Zookeeper读书笔记-3】客户端原理

1 基础概念

ClientCnxn是网络连接器,管理客户端与服务端的网络交互。

ClientWatchManager保存客户端的watcher

HostProvider服务器地址列表管理器

outgoingQueue客户端的请求发送队列

pendingQueue客户端的服务端响应等待队列

SendThread管理客户端与服务端的所有网络IO

客户端的SendThread通过一定频率向服务端发送PING包实现心跳检测,维护客户端与服务端的会话生命周期;

会话周期内客户端与服务端之间出现TCP连接断开,会自动重连,这个过程是透明的;

 

SendThread管理客户端所有的请求发送与响应接收;

SendThread将服务端事件传递给EventThread去处理;

EventThread处理客户端的事件,触发客户端注册的Watcher监听。

2 客户端初始化与启动过程

  1. 设置默认watcher
  2. 设置Zookeeper服务器地址列表
  3. 创建ClientCnxn

创建Zookeeper构造方法中传入watcher对象,则此watcher对象会被保存入defaultWatcher中,作为客户端会话期间默认的watcher。

2.1 会话创建的初始化阶段

1 初始化Zookeeper对象,创建的客户端Watcher管理器ClientWatcherManager

2 设置会话默认Watcher,创建Zookeeper对象是传入的Watcher对象会被保存入ClientWatcherManager

3 构造Zookeeper服务器地址列表管理器HostProvider

4 创建并初始化客户端网络连接起ClientCnxn,管理客户端与服务端的网络交互;

    同时客户端会初始化队列outgoingQueue用于客户端的请求发送队列和pendingQueue用于服务端响应的等待队列;

    同时客户端还要创建ClientCnxnSocket,作为底层IO处理器

5 初始化网络线程SendThread管理客户端与服务端的网络连接,使用ClientCnxnSocket作为底层IO处理器

   初始化网络线程EventThread处理客户端的事件,初始化待处理事件队列waitingEvents,存放所有等待被客户端处理的事件。

2.2 会话创建阶段 

6 启动SendThread,EventThread

   SendThread首先判断客户端的状态,进行一些清理工作,为客户端发送”会话创建“请求做准备。

7 获取一个服务器地址列表

   SendThread首先从HostProvider随机获取一个Zookeeper地址,交给ClientCnxnSocket去创建与Zookeeper服务器之间的TCP连接。

8 创建TCP连接

获取到一个服务器地址,ClientCnxnSocket负责与服务器创建一个TCP长连接

9 构造connectRequest请求

SendThread负责构造ConnectRequest,该请求代表客户端要与服务端连接创建会话。ZK客户端还会将该请求包装成网络层的Packet对象,放入请求发送队列outgoingQueue中。

10 发送请求

ClientCnxnSocket从outgoingQueue取出一个代发送的Packet对象,序列化成ByteBuffer对象向服务端发送

2.3 响应处理阶段

11 接收服务端响应

ClientCnxnSocket接到服务端响应,首先判断当前客户端状态是否是“已初始化”,如果未初始化就认为此响应是会话创建请求的响应,直接由readConnectResult方法处理该响应。

12 处理Response

ClientCnxnSocket对服务端响应反序列化,得到ConnectResponse对象,并获取ZK服务端分配的会话SessionId。

13 连接成功

连接成功后,同志SendThread线程进一步设置readTimeout,connectTimeout等参数,并更新客户端状态;

通知地址管理器HostProvider当前成功连接的服务器地址。

14 生成事件SyncConnected-None

SendThread会生成事件,目的是上层应用感知会话创建成功。代表客户端与服务端的会话创建成功,并将该事件传递给EventThread线程。

15 获取Watcher

EventThread收到事件后从ClientWatcherManager中获取对应的watcher,针对SyncConnected-None直接找出步骤2中存储的默认watcher,放入EventThread中的waitingEvents队列中。

16 处理事件

EventThread从waitingEvents队列中获取待处理的watcher对象,调用该对象的process方法。

2.4 服务器地址列表

创建ZK客户端时传入的服务器地址列表时如何生效的?按照顺序连接各个服务器还是随机连接?

服务器地址列表解析器ConenctStringParser将传入的地址列表解析成chrootPath,并且保存下服务器地址列表

- chroot指的是每个客户端为自己设置命名空间,之后该客户端的操作都会限定在自己的命名空间内。例如“192.168.1.1:2181, 192.168.1.2:2181/apps/a”

- ConenctStringParser将IP以及port封装到InetSocketAddress对象,以ArrayList形式保存入ConenctStringParser.serverAddresses属性中,经过处理的地址列表会被进一步封装到StaticHostProvider(提供服务器地址个数,地址列表,回调方法用于客户端与服务端创建连接成功)。

StaticHostProvider实现了接口HostProvider

- 解析地址与端口,封装成集合

- 调用Collections.shuffle将地址列表打散,组装成环形循环队列,使用过程中从这个队列获取地址信息

2.5 网络IO

1 请求发送

outgoingQueue队列中提取出一个可以发送的Packet对象,同时生成客户端请求序号XID,并将其设置到Packet请求头中,然后序列化并发送。

请求发送完毕,立即将Packet保存到pendingQueue中,等待服务端响应后进行相应处理。

2 响应接收

客户端接到服务端响应后,根据客户端请求类型不同,进行不同的处理。

客户端还未初始化,说明客户端与服务端正在创建会话,直接将接到的ByteBuffer(incomingBuffer)序列化成ConnectResponse对象。

客户端处于正常的会话周期,并且接到的服务端响应是一个事件,客户端将接到的ByteBuffer(incomingBuffer)序列化成WatcherEvent对象,并将该对象放入待处理队列。

如果是一个常规请求(Create,GetData,Exists等操作),从pendingQueue队列中取出一个Packet对象进行处理。客户端检查服务端响应中包含的XID确保请求处理顺序,然后将接到的ByteBuffer(incomingBuffer)序列化成Response对象。

finishPacket方法中处理Watcher注册等逻辑。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值