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 closingif (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, herenow = System.currentTimeMillis();            for (SelectionKey k : selected) {… …                if (doIO()) {lastHeard = now;}… …}}        catch() {… …}}

这里用了java的nio功能,当selector侦测到事件发生的时候就会触发一次循环,主要的操作会在doIO()里面完成:

    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有一些帮助。对于文章中没有介绍或者没有说清楚的地方需要进一步查看源码来解决。

转自 http://www.spnguru.com/2010/08/zookeeper%E5%85%A8%E8%A7%A3%E6%9E%90%E2%80%94%E2%80%94client%E7%AB%AF/

转载于:https://blog.51cto.com/2933246/1759181

Zookeeper全解析——Client端相关推荐

  1. Zookeeper全解析——Paxos作为灵魂

    Zookeeper全解析--Paxos作为灵魂 原计划在介绍完ZK Client之后就着手ZK Server的介绍,但是发现ZK Server所包含的内容实在太多,并不是简简单单一篇Blog就能搞定的 ...

  2. 4、利用zookeeper来实现client端自动感知服务器端在线情况,并且可以进行负载均衡。...

    2019独角兽企业重金招聘Python工程师标准>>> #1:业务需求 客户端需要及时的知道当前服务器集群中那些服务器在线以及服务器的负载线程数. 并且取其中线程负载最小的服务器进行 ...

  3. 轻量级Rpc框架设计--motan源码解析六:client端服务发现

    一, Client端初始化工作 client端通过RefererConfigBean类实现InitializingBean接口的afterPropertiesSet方法, 进行下面三项检查配置工作: ...

  4. 后端/服务端开发方向面试题全解析

    笔者在 2020 届秋招中斩获了京东.网易.去哪儿网等10余家互联网公司的校招 Offer.本 Chat 针对后端.服务端开发方向,分类的详细讲解后端服务端开发方向的面试题目,希望能够帮助到大家,在面 ...

  5. Java 面试全解析:核心知识点与典型面试题

    课程背景 又逢"金九银十",年轻的毕业生们满怀希望与忐忑,去寻找.竞争一个工作机会.已经在职的开发同学,也想通过社会招聘或者内推的时机争取到更好的待遇.更大的平台. 然而,面试人群 ...

  6. Python 常见的 170 道面试题全解析:2022 版

    Python 常见的 170 道面试题全解析:2019 版 语言特性 1.谈谈对 Python 和其他语言的区别 答:Python 是一门语法简洁优美,功能强大无比,应用领域非常广泛,具有强大完备的第 ...

  7. OkHttp全解析(一)——基本概念与使用方法

    目录 1.背景 2.基本概念 3.使用方法 4.总结 5.参考 1.背景 kHttp全解析系列文章分为三个部分,包括基本概念与使用方法.原理解析.高级特性的解析.本文为第一部分,基本概念与使用方法,适 ...

  8. 第二篇:可靠连接,TCP协议全解析

    文章目录 一.前言 二.TCP报文结构 三.TCP连接(重点:三次握手和四次挥手) 3.1 三次握手建立连接 3.2 四次挥手释放连接 3.3 wireshark演示 四.TCP可靠连接 4.1 序号 ...

  9. 最全解析:支付宝钱包系统架构内部揭秘

        亿邦动力网App电商新闻全新栏目--每日一干,与广大电商同胞相约每晚8:30,献上最精彩的一"干".如果你也有关于电商领域的运营法宝.营销创意.管理迷津......欢迎投稿 ...

最新文章

  1. Wireshark技巧-过滤规则和显示规则
  2. 定了!网易CEO丁磊6月11日快手直播带货
  3. Netty 高性能架构设计
  4. Docker 删除所有容器和镜像,从头来过!
  5. Illustrator2020中文版教程,如何在AI中使用蒙版来裁剪内容?
  6. PHP获取指定月的前N个月数据
  7. 单片机c语言带参数子函数,单片机C语言教程:C51函数
  8. TS2339: Property 'debounceTime' does not exist on type 'Observableany'. - Angular 6
  9. 计算机usb口设置方法,如何在电脑上设定usb端口权限
  10. 反思: Google 为何把 SurfaceView 设计的这么难用?
  11. python文件双击闪退_解决python文件双击运行秒退的问题
  12. EXCEL 公式中 sheet名字 用 单元格值 代替
  13. 2022湖南株洲服饰产业数智互联网峰会暨湖南服饰产业互联网高峰论坛成功举办
  14. Oracle Grid Infrastructure架构
  15. 利用干支年反推公元年份的计算公式推导
  16. python安装环境变量出错_在windows 10上安装twisted时出错。INCLUDE环境变量为空
  17. chewing的作业——数字信封实现文件传输
  18. Unity scene game 屏幕效果相机管理学习
  19. 2.06-外设篇-串口
  20. 「工具」不限速的百度网盘工具

热门文章

  1. 使用tcl文件分配管脚
  2. python 连接sql server
  3. JVM参数之-XX:+HeapDumpOnOutOfMemoryError(导出内存溢出的堆信息(hprof文件))
  4. krpano音量控制(我们已经转移到krpano中国网站 krpano360.com)
  5. [Leetcode][JAVA] Populating Next Right Pointers in Each Node II
  6. 需要学习的技术知识备忘录
  7. 模板类成员函数特例化写法
  8. 内联函数、默认参数和函数占位参数
  9. vscode 连接服务器jupyter_VScode中使用jupyter notebook
  10. jieba 词典 词频_python jieba分词(添加停用词,用户字典 取词频