Zookeeper之Zookeeper底层客户端架构实现原理(转载)
Zookeeper的Client直接与用户打交道,是我们使用Zookeeper的interface。了解ZK Client的结构和工作原理有利于我们合理的使用ZK,并能在使用中更早的发现问题。本文将在研究源码的技术上讲述ZK Client的工作原理及内部工作机制。
在看完ZK Client的大致架构以后我希望能有一种简单的方式描述ZK Client的基本结构,想来想去我觉得还是图片比较能反映情况,于是我画了这张大致的结构图:
我想既然我画了这张图,就让我们从这张图开始讲起吧。

模块:
我们可以认为ZK的Client由三个主要模块组成:Zookeeper, WatcherManager, ClientCnxn
Zookeeper是ZK Client端的真正接口,用户可以操作的最主要的类,当用户创建一个Zookeeper实例以后,几乎所有的操作都被这个实例包办了,用户不用关心怎么连接到Server,Watcher什么时候被触发等等令人伤神的问题。
WatcherManager,顾名思义,它是用来管理Watcher的,Watcher是ZK的一大特色功能,允许多个Client对一个或多个 ZNode进行监控,当ZNode有变化时能够通知到监控这个ZNode的各个Client。我们把一个ZK Client简单看成一个Zookeeper实例,那么这个实例内部的WatcherManager就管理了ZK Client绑定的所有Watcher。
ClientCnxn是管理所有网络IO的模块,所有和ZK Server交互的信息和数据都经过这个模块,包括给ZK Server发送Request,从ZK Server接受Response,以及从ZK Server接受Watcher Event。ClientCnxn完全管理了网络,从外部看来网络操作是透明的。
线程:
每当我们创建一个Zookeeper实例的时候,会有两个线程被创建:SendThread和EventThread。所以当我们使用ZK Client端的时候应该尽量只创建一个Zookeeper实例并反复使用。大量的创建销毁Zookeeper实例不仅会反复的创建和销毁线程,而且会在 Server端创建大量的Session。
SendThread是真正处理网络IO的线程,所有通过网络发送和接受的数据包都在这个线程中处理。这个线程的主体是一个while循环:
while (zooKeeper.state.isAlive()) { try { if (sockKey == null) { // don’t re-establish connection if we are closing if (closing) { break; } startConnect(); lastSend = now; lastHeard = now; } … …. selector.select(to); Set<SelectionKey> selected; synchronized (this) { selected = selector.selectedKeys(); } // Everything below and until we get back to the select is // non blocking, so time is effectively a constant. That is // Why we just have to do this once, here now = System.currentTimeMillis(); for (SelectionKey k : selected) { … … if (doIO()) { lastHeard = now; } … … } } catch() { … … } }复制代码 |
这里用了java的nio功能,当selector侦测到事件发生的时候就会触发一次循环,主要的操作会在doIO()里面完成:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
boolean doIO() throws InterruptedException, IOException { boolean packetReceived = false; SocketChannel sock = (SocketChannel) sockKey.channel(); if (sock == null) { throw new IOException(“Socket is null!”); } if (sockKey.isReadable()) { … … } if (sockKey.isWritable()) { … … } if (outgoingQueue.isEmpty()) { disableWrite(); } else { enableWrite(); } return packetReceived;} |
这个过程大概是这样的:
1. 如果有数据可读,则读取数据包,如果数据包是先前发出去的Request的Response,那么这个数据包一定在Pending Queue里面。将它从Pending Queue里面移走,并将此信息添加到Waiting Event Queue 里面,如果数据包是一个Watcher Event,将此信息添加到Waiting Event Queue里面。
2. 如果OutgoingQueue里面有数据需要发送,则发送数据包并把数据包从Outgoing Queue移至Pending Queue,意思是数据我已经发出去了,但还要等待Server端的回复,所以这个请求现在是Pending 的状态。
另外一个线程EventThread是用来处理Event的。前面提到SendThread从Server收到数据的时候会把一些信息添加到 Event Thread里面,比如Finish Event和Watcher Event。EventThread就是专门用来处理这些Event的,收到Finish Event的时候会把相对应的Package置成Finish状态,这样等待结果的Client函数就能得以返回。收到Watcher Event的时候会联系WatcherManager找到相对应的Watcher,从WatcherManager里面移除这个Watcher(因为每个 Watcher只会被通知一次) 并回调Watcher的process函数。所以所有Watcher的process函数是运行在EventThread里面的。
保持连接:
到目前为止应该已经大概介绍了ZK Client端的大致结构和处理流程。还剩下一个问题就是当网络出问题时ZK Client是如何处理的。其实这个过程并不复杂,大概是执行以下步骤:
1. 网络发生故障,网络操作抛出的异常被捕获。
2. 确认网络操作失败,清除当前与Server相关的网络资源,包括Socket等等。
3. 在Server列表中逐个尝试链接Server。
这个过程从外界看来是透明的,外界并不会觉察到ZK Client已经悄悄地更换了一个连接的Server。
好了,对于ZK Client的介绍大概就这么多了,希望这样的介绍对于大家学习和使用Zookeeper有一些帮助。对于文章中没有介绍或者没有说清楚的地方需要进一步查看源码来解决。
Zookeeper之Zookeeper底层客户端架构实现原理(转载)的更多相关文章
- zookeeper(4)--zookeeper分布式锁原理
目前几乎很多大型网站及应用都是分布式部署的,分布式场景中的数据一致性问题一直是一个比较重要的话题.分布式的CAP理论告诉我们“任何一个分布式系统都无法同时满足一致性(Consistency).可用性( ...
- zookeeper(3) zookeeper的实践及原理
一.基于java API初探zookeeper的使用 (1)建立连接 public static void main(String[] args) { //NOT_CONNECTED-->CON ...
- Zookeeper--0300--java操作Zookeeper,临时节点实现分布式锁原理
删除Zookeeper的java客户端有 : 1,Zookeeper官方提供的原生API, 2,zkClient,在原生api上进行扩展的开源java客户端 3, 一.Zookeeper原生API ...
- ZooKeeper学习笔记(二)——内部原理
zookeeper学习笔记(二)--内部原理 1. zookeeper的节点的类型 总的来说可以分为持久型和短暂型,主要区别如下: 持久:客户端与服务器端断开连接的以后,创建的节点不会被删除: 持久化 ...
- zookeeper图形化的客户端工具
追加一个zookeeper图形化的客户端工具: 1.zookeeper图像化客户端工具的下载地址:https://issues.apache.org/jira/secure/attachment/12 ...
- zookeeper(一):功能和原理
简介 ZooKeeper 是一个开源的分布式协调服务,由雅虎创建,是 Google Chubby 的开源实现.分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅.负载均衡.命名服务.分 ...
- java架构之路-(分布式zookeeper)zookeeper集群配置和选举机制详解
上次博客我们说了一下zookeeper的配置文件,以及命令的使用https://www.cnblogs.com/cxiaocai/p/11597465.html.我们这次来说一下我们的zookeepe ...
- zookeeper系列(一)zookeeper图形化的客户端工具
追加一个zookeeper图形化的客户端工具: 1.zookeeper图像化客户端工具的下载地址:https://issues.apache.org/jira/secure/attachment/12 ...
- zookeeper篇-zookeeper客户端和服务端的基础命令
点赞再看,养成习惯,微信搜索「小大白日志」关注这个搬砖人. 文章不定期同步公众号,还有各种一线大厂面试原题.我的学习系列笔记. 前提:我把zookeepee安装在了服务器/usr/local/java ...
随机推荐
- 高级Bash脚本编程指南《Advanced Bash-Scripting Guide》 in Chinese
<Advanced Bash-Scripting Guide> in Chinese <高级Bash脚本编程指南>Revision 10中文版 在线阅读链接:http://ww ...
- 洛谷.2596.[ZJOI2006]书架(Splay)
题目链接 /* 五个操作: 1.将某元素置顶.删掉这个数,插入最左 2.将某元素置底.同样 3.旋到根后,直接将这个数与前驱/后继交换所有信息 不是左右子节点! 4.5.裸平衡树 ps:1.用pos[ ...
- JVM笔记(一)数字在JVM中的表示
数字在JVM中的表示 一.整数在JVM中的表示 1.在Java虚拟机中,整数有四种表示: byte:8位 short:16位 int:32位 long:64位 2.原码. ...
- Python常见下划线
python中常见的下划线意义 Python中常常使用下划线里对变量进行修饰,通常作为变量的前缀或者后缀出现,被修饰的变量一般存在特殊的用法: _XXX:不能被from module import _ ...
- 判断socket连接是否失效
http://blog.csdn.net/jazywoo123/article/details/8693661 http://www.itnose.net/st/141698-pn11.html
- Assigning to 'id<UINavigationControllerDelegate,UIImagePickerControllerDelegate> _Nullable' from incompatible type 'InfchangeVC *const __strong'
出现 Assigning to 'id<UINavigationControllerDelegate,UIImagePickerControllerDelegate>' from inco ...
- Android MediaPlayer架构 -- MediaPlayer的创建过程
本文系作者自己学习之所用,文章内容仅出自作者拙劣之思考,问题之处烦请不吝指教. MediaPlayer 能被用来控制音/视频文件或流媒体的回放.Android中以MediaPlayer类作为音视频播放 ...
- Hadoop学习博客
http://zy19982004.iteye.com/blog/monthblog_more
- Java svnkit check update commit
import java.io.File; import org.apache.log4j.Logger;import org.tmatesoft.svn.core.SVNCommitInfo;impo ...
- Zookeeper学习笔记——1 单机版本环境搭建
下载 首先去官网下载: http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.11/ 然后执行tar -zxvf解压 启动 进入conf目录, ...