一、前言

  前篇博客分析了Zookeeper的序列化和通信协议,接着继续学习客户端,客户端是开发人员使用Zookeeper最主要的途径,很有必要弄懂客户端是如何与服务端通信的。

二、客户端

  2.1 客户端组成

  Zookeeper客户端主要由如下核心部件构成。

  1. Zookeeper实例,客户端入口。

  2. ClientWatchManager, 客户端Watcher管理器。

  3. HostProvider,客户端地址列表管理器。

  4. ClientCnxn,客户端核心线程,内部包含了SendThread和EventThread两个线程,SendThread为I/O线程,主要负责Zookeeper客户端和服务器之间的网络I/O通信;EventThread为事件线程,主要负责对服务端事件进行处理。

  Zookeeper客户端初始化与启动环节,就是Zookeeper对象的实例化过程。客户端在初始化和启动过程中大体可以分为如下3个步骤

  1. 设置默认Watcher

  2. 设置Zookeeper服务器地址列表

  3. 创建ClientCnxn。

  若在Zookeeper构造方法中传入Watcher对象时,那么Zookeeper就会将该Watcher对象保存在ZKWatcherManager的defaultWatcher中,并作为整个客户端会话期间的默认Watcher。

  2.2 会话的创建

  下图表示了客户端与服务端会话建立的整个过程,包括初始化阶段(第一阶段)、会话创建阶段(第二阶段)、响应处理阶段(第三阶段)三个阶段。

  2.3 服务器地址列表

  在实例化Zookeeper时,用户传入Zookeeper服务器地址列表,如192.168.0.1:2181,192.168.0.2:2181,192.168.0.3:2181,此时,Zookeeper客户端在连接服务器的过程中,是如何从这个服务器列表中选择服务器的呢?Zookeeper收到服务器地址列表后,会解析出chrootPath和保存服务器地址列表。

  1. Chroot,每个客户端可以设置自己的命名空间,若客户端设置了Chroot,此时,该客户端对服务器的任何操作都将被限制在自己的命名空间下,如设置Choot为/app/X,那么该客户端的所有节点路径都是以/app/X为根节点。

  2. 地址列表管理,Zookeeper使用StaticHostProvider打散服务器地址(shuffle),并将服务器地址形成一个环形循环队列,然后再依次取出服务器地址。

  2.4 网络I/O

  ClientCnxn是Zookeeper客户端中负责维护客户端与服务端之间的网络连接并进行一系列网络通信的核心工作类,Packet是ClientCnxn内部定义的一个堆协议层的封装,用作Zookeeper中请求和响应的载体。Packet包含了请求头(requestHeader)、响应头(replyHeader)、请求体(request)、响应体(response)、节点路径(clientPath/serverPath)、注册的Watcher(watchRegistration)等信息,然而,并非Packet中所有的属性都在客户端与服务端之间进行网络传输,只会将requestHeader、request、readOnly三个属性序列化,并生成可用于底层网络传输的ByteBuffer,其他属性都保存在客户端的上下文中,不会进行与服务端之间的网络传输

  ClientCnxn维护着outgoingQueue(客户端的请求发送队列)和pendingQueue(服务端响应的等待队列),outgoingQueue专门用于存储那些需要发送到服务端的Packet集合,pendingQueue用于存储那些已经从客户端发送到服务端的,但是需要等待服务端响应的Packet集合。

  在正常情况下,会从outgoingQueue中取出一个可发送的Packet对象,同时生成一个客户端请求序号XID并将其设置到Packet请求头中去,然后序列化后再发送,请求发送完毕后,会立即将该Packet保存到pendingQueue中,以便等待服务端响应返回后进行相应的处理。

  客户端获取到来自服务端的完整响应数据后,根据不同的客户端请求类型,会进行不同的处理。

  1. 若检测到此时客户端尚未进行初始化,那么说明当前客户端与服务端之间正在进行会话创建,直接将接收的ByteBuffer序列化成ConnectResponse对象。

  2. 若当前客户端已经处于正常会话周期,并且接收到服务端响应是一个事件,那么将接收的ByteBuffer序列化成WatcherEvent对象,并将该事件放入待处理队列中。

  3. 若是一个常规请求(Create、GetData、Exist等),那么从pendingQueue队列中取出一个Packet来进行相应处理。首先会检验响应中的XID来确保请求处理的顺序性,然后再将接收到的ByteBuffer序列化成Response对象。

  SendThread是客户端ClientCnxn内部的一个核心I/O调度线程,用于管理客户端与服务端之间的所有网络I/O操作,在Zookeeper客户端实际运行中,SendThread的作用如下:

  1. 维护了客户端与服务端之间的会话生命周期(通过一定周期频率内向服务端发送PING包检测心跳),如果会话周期内客户端与服务端出现TCP连接断开,那么就会自动且透明地完成重连操作。

  2. 管理了客户端所有的请求发送和响应接收操作,其将上层客户端API操作转换成相应的请求协议并发送到服务端,并完成对同步调用的返回和异步调用的回调。

  3. 将来自服务端的事件传递给EventThread去处理。

  EventThread是客户端ClientCnxn内部的一个事件处理线程,负责客户端的事件处理,并触发客户端注册的Watcher监听。EventThread中的watingEvents队列用于临时存放那些需要被触发的Object,包括客户端注册的Watcher和异步接口中注册的回调器AsyncCallback。同时,EventThread会不断地从watingEvents中取出Object,识别具体类型(Watcher或AsyncCallback),并分别调用process和processResult接口方法来实现对事件的触发和回调。

三、总结

  本篇博文讲解了客户端的相关细节,内容较为简单易懂,该模块知识会为之后分析源码打下好的基础,谢谢各位园友观看~  

【分布式】Zookeeper客户端的更多相关文章

  1. 【分布式】Zookeeper客户端基本的使用

    与mysql.redis等软件一样,zookeeper的软件包中也提供了客户端程序用于对服务器上的数据进行操作.本节我们就来学习zookeeper客户端的使用方法.不过在详细讲解zk客户端的使用方法之 ...

  2. zookeeper 客户端编程

    zookeeper是一个分布式的开源的分布式协调服务,用它可以来现同步服务,配置维护.zookeeper的稳定性也是可以保证的,笔者曾参与过的使用zookeeper的两个应用,一个是用zookeepe ...

  3. zookeeper客户端操作

    ZooKeeper客户端 zkCli.sh 节点的增删改查 在 bin 目录下的  zkCli.sh  就是ZooKeeper客户端 ./zkCli.sh -timeout 5000  -server ...

  4. Zookeeper客户端Curator基本API

    在使用zookeper的时候一般不使用原生的API,Curator,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连.反复注册Watcher和NodeExistsExceptio ...

  5. Zookeeper客户端Curator的使用,简单高效

    Curator是Netflix公司开源的一个Zookeeper客户端,与Zookeeper提供的原生客户端相比,Curator的抽象层次更高,简化了Zookeeper客户端的开发量. 1.引入依赖: ...

  6. ZooKeeper客户端 zkCli.sh 节点的增删改查

    zkCli.sh 在 bin 目录下的  zkCli.sh  就是ZooKeeper客户端 ./zkCli.sh -timeout 5000  -server 127.0.0.1:2181  客户端与 ...

  7. Zookeeper客户端Curator使用详解

    Zookeeper客户端Curator使用详解 前提 最近刚好用到了zookeeper,做了一个基于SpringBoot.Curator.Bootstrap写了一个可视化的Web应用: zookeep ...

  8. zookeeper(六):Zookeeper客户端Curator的API使用详解

    简介 Curator是Netflix公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连.反复注册Watcher和NodeExistsEx ...

  9. Zookeeper客户端对比选择_4

    Zookeeper客户端对比选择 本文思维导图 使用框架的好处是自带一套实用的API,但是Zookeeper虽然非常强大,但是社区却安静的可怕,版本更新较慢,下面会先从zookeeper原生API的不 ...

随机推荐

  1. SDWebImage源码解读 之 SDWebImageCompat

    第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...

  2. 最长回文子串-LeetCode 5 Longest Palindromic Substring

    题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...

  3. 深入.NET平台和C#编程总结大全

    对于初学者的你,等到你把这个看完之后就更清楚地认知.NET和C#编程了,好了废话不多说,开始吧!                                                     ...

  4. Java中,异常的处理及抛出

    首先我们需要知道什么是异常? 常通常指,你的代码可能在编译时没有错误,可是运行时会出现异常.比如常见的空指针异常.也可能是程序可能出现无法预料的异常,比如你要从一个文件读信息,可这个文件不存在,程序无 ...

  5. 集合(set)-Python3

    set 的 remove() 和 discard()  方法介绍. 函数/方法名   等价操作符 说明 所有集合类型 len(s)   集合基数:集合s中元素个数 set([obj])   可变集合工 ...

  6. java 泛型

    1.Student stu =tool.getObj();右边得到的是Object类型,需要向下转型,强转换. 2. 3. 4.泛型方法不能被静态修饰这样写 5.如果想定义定义静态泛型方法,只能这样写 ...

  7. Yeoman 学习笔记

    yoeman 简介:http://www.infoq.com/cn/news/2012/09/yeoman yeoman 官网: http://yeoman.io/ yeoman 是快速创建骨架应用程 ...

  8. Lesson 16 A polite request

    Text If you park your car in the wrong place, a traffic policeman will soon find it. You will be ver ...

  9. Ubuntu部署python3.5的开发和运行环境

    Ubuntu部署python3.5的开发和运行环境 1 概述 由于最近项目全部由python2.x转向 python3.x(使用目前最新的 python3.5.1) ,之前的云主机的的默认python ...

  10. 如何用 MEF 扩展应用程序

    最近在写一篇关于如何扩展 Visual Studio 编辑器的文章时,用到了 MEF,因此打算写一篇文章提一下这个技术点.本篇文章并不打算详细介绍 MEF,只是一个最简单的入门,相信您在阅读本篇文章后 ...