Zookeeper之Zookeeper的Client的分析

1)几个重要概念

  • ZooKeeper:客户端入口
  • Watcher:客户端注册的callback
  • ZooKeeper.SendThread: IO线程
  • ZooKeeper.EventThread: 事件处理线程,处理各类消息callback
  • ClientCnxnSocketNIO:继承自ClientCnxnSocket,专门处理IO

2)zookeeper初始化

    • 应用提供watch实例
    • 实例化zookeeper
      • 实例化socket,默认使用ClientCnxnSocketNIO,可通过zookeeper.clientCnxnSocket配置定制
      • 实例化ClientCnxn
      • 实例化SendThread
      • 实例化EventThread
    • 启动zookeeper
      • 启动SendThread
        • 连接服务器(见SendThread.startConnect)
          • 产生真正的socket,见ClientCnxnSocketNIO.createSock
          • 向select注册一个OP_CONNECT事件并连接服务器,由于是非阻塞连接,此时有可能并不会立即连上,如果连上就会调用SendThread.primeConnection初始化连接来注册读写事件,否则会在接下来的轮询select获取连接事件中处理
          • 复位socket的incomingBuffer
          • 连接成功后会产生一个connect型的请求发给服务,用于获取本次连接的sessionid
          • 进入循环等待来自应用的请求,如果没有就根据时间来ping 服务器
    • 启动EventThread
      • 开始进入无限循环,从队列waitingEvents中获取事件,如果没有就阻塞等待

3)以一个请求为例以 zk.exists("/root", false)为例

  • 客户端线程
    • 构造一个exists类型的请求,请求类型见ZooDefs.OpCode
    • 将请求构造成一个Packet,并将该packet放入outgoingQueue
      • 唤醒select
    • 阻塞等待结果
  • SendThread
    • 通过select 轮询判断是否有socket准备好,如果能读就读,能写就写
    • 此时socket准备好写了 ,就从outgoingQueue获取packet, 将packet发送到服务端
    • 一旦发送了一个完整的packet,就将packet从outgoingQueue移除
    • 最后将packet加入到pendingQueue
    • 再次select轮询看是否有响应数据,如果有首先都去4个字节的响应头(包含响应的长度信息),然后在下一次遍历中都去响应体
    • 都到响应将packet从pendingQueue移除
    • 如果该请求packet带有一个callback,那么会将此packet放入waitingEvents队列,让EventThread去处理
    • 最后会调用p.notifyAll()解锁,于是应用线程从阻塞中出来
  • 如果使用了带callback 的exists,EventThread会干活

4)小结

4.1)

SendThread也并非完全对应与请求/响应模式,SendThread也会接受到节点变化的通知,此时客户端变成了服务端

4.2)时间和超时的控制

ClientCnxnSocket作为ClientCnxnSocketNIO的父类,

有3个关键的时间字段

  • now :每次轮询select之前更新,或者发生错误是在catch段中更新为当前时间
  • lastHeard:在读取了响应,包括上面提到的connect型请求和常规命令型请求的响应以及完成网络连接时更新为当前时间
  • lastSend:每次发送完ping 命令和请求以及完成网络连接时更新为当前时间

有下面几个超时设置

  • sessionTimeout:zookeeper初始化时设置的
  • readTimeout:sessionTimeout * 2 / 3
  • connectTimeout:sessionTimeout / hostProvider.size();  //hostProvider.size()为zookeeper服务器个数
  • getIdleRecv():now - lastHeard
  • getIdleSend():now - lastSend
  • SessionTimeout的计算
    • 如果没有完成连接to=connectTimeout - getIdleRecv()
    • 如果完成连接to=readTimeout - getIdleRecv()
    • 如果to<=0  就会抛出SessionTimeoutException

4.3)什么时候ping

计算timeToNextPing = readTimeout / 2-getIdleSend()

如果timeToNextPing <= 0,发送ping请求(只是将ping请求放入outgoingQueue,并不发生IO)

4.4)select阻塞多久

如果上述的0<timeToNextPing<to,那么阻塞时长为timeToNextPing,否则为to

如果有写请求,select会被唤醒

4.5)sendThread的工作原理

该线程作为zookeeper客户端的核心部分专门负责IO处理

  • 计算select timeout(上面提到的to)
  • 检查空闲时间,有可能抛出SessionTimeoutException或者发送ping
  • 使用select轮询,获取网络事件(连接、读、写)也就是这3类
    • 如果是连接,做连接处理
    • 如果读,过程如下
      • 读取消息头,4个字节,头包含了消息体的字节数
      • 读 取消息体,分为两个大类消息,连接型消息“connect”和非连接型消息“header”,前者上面提到过就是连接完成之后发的一种消息,用于确定 sessionid, 另外前者会调用sendThread.onConnected,后者会调用sendThread.readResponse
      • 非连接型消息有分为几类
        • ping 消息
        • auth认证消息
        • 订阅的消息,即各种变化的通知,比如子节点变化、节点内容变化,由服务器推过来的消息 ,获取到这类消息或通过eventThread.queueEvent将消息推入事件队列
        • 客户端命令的response,如果此消息带有callback着通过eventThread.queuePacket推入事件队列,否者唤醒阻塞的应用线程,注意到客户端命令都会有阻塞版本和异步版本(带callback)
    • 如果是写,就从outgoingQueue获取packet,写入网络

4.6)请求中的Watcher和StatCallback的差别

两个都是callback,两者都由EventThread,但后者控制调用线程是否会阻塞等待响应

4.7)IO模型

如图

  • 没有使用传统连接池,会和zookeeper集群中的一台相连
  • 单IO线程(NIO)+事件线程,很标准的NIO模式
时间: 2024-11-05 14:39:18

Zookeeper之Zookeeper的Client的分析的相关文章

zookeeper 学习 zookeeper下载部署

下载 http://mirror.bit.edu.cn/apache/zookeeper/ 校验 解压后得到zookeeper-3.4.10.jar,使用md5sum zookeeper-3.4.10.jar 得到 450dbad05d829607bc45b9ccad789890  zookeeper-3.4.10.jar 与zookeeper-3.4.10.jar.md5中的内容比较 伪集群部署 以server0为例 [email protected]:~/server0/zookeeper/

Zookeeper - 什么是Zookeeper,以及zookeeper的安装(1)

Zookeeper 什么是Zookeeper? 官网传送门 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护.域名服务.分布式同步.组服务等. 从设计模式来说基于观察者模式设计的分布式服务管理框架,存储大家都关心的数据,然后接受观察者的注册.一旦这些数据状态发生变化,zookeeper就将负责通知已经注册的观察者做出反应. Zoo

【Zookeeper】zookeeper简单介绍和适用场景

什么是zookeeper ZooKeeper是用于维护配置信息,命名,提供分布式同步以及提供组服务的集中式服务. zookeeper数据结构 zookeeper数据结构简单的可以看成树状结构.每个节点最大只能存储1M的数据. zookeeper特点 主从:集群中一个领导者,多个跟随者 半数机制:集群中半数以上存活,才能正常工作 数据一致性:集群中无弄领导者还是跟随者数据都是一样的. 顺序性:来自同一个client的更新请求按照其发送顺序依次执行. 数据更新原子性:更新成功或失败.没有部分结果.

ERROR [main] zookeeper.RecoverableZooKeeper: ZooKeeper create failed after 4 attempts

ERROR [main] zookeeper.RecoverableZooKeeper: ZooKeeper create failed after 4 attempts ERROR [main] master.HMasterCommandLine: Master exiting java.lang.RuntimeException: Failed construction of Master: class org.apache.hadoop.hbase.master.HMaster more…

什么是Zookeeper,Zookeeper的作用是什么,在Hadoop及hbase中具体作用是什么

什么是Zookeeper,Zookeeper的作用是什么,它与NameNode及HMaster如何协作?在没有接触Zookeeper的同学,或许会有这些疑问.这里给大家总结一下. 一.什么是Zookeeper  ZooKeeper 顾名思义 动物园管理员,他是拿来管大象(Hadoop) . 蜜蜂(Hive) . 小猪(Pig)  的管理员, Apache Hbase和 Apache Solr 以及LinkedIn sensei  等项目中都采用到了 Zookeeper.ZooKeeper是一个分

Zookeeper 3.4.6 Client端流程粗略梳理

首先从Zookeeper入手,Zookeeper-->ClientCnxn-->sendThread/eventThread public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, boolean canBeReadOnly) throws IOException { LOG.info("Initiating client connection, connectString="

canal挂载在zookeeper,java客户端client,连接报超时

用canal解析mysql的binlog,客户端client用的zookeeper的地址, 会报超时错误,主机ping 虚拟机(192.****.125)的也能ping的通,哪个大佬帮忙是看看是怎么回事? 原文地址:https://www.cnblogs.com/4668754ijn/p/11465180.html

zookeeper(8)源码分析-事件监听Watcher(1)

Watcher是zookeeper的事件监听机制,今天我们来看看Watcher类的代码都包含了什么内容? Watcher Watcher是一个接口,定义了process方法,需要子类实现.其代表了实现Watcher接口时必须实现的的方法,即定义进行处理,WatchedEvent表示观察的事件. abstract public void process(WatchedEvent event); 内部类 1.Event接口 表示事件代表的状态,其包含了KeeperState和EventType两个内

zookeeper(9)源码分析-事件监听Watcher(2)

接着上一篇文章,继续分析和Watcher相关的类的源码. ClientWatchManager public Set<Watcher> materialize(Watcher.Event.KeeperState state, Watcher.Event.EventType type, String path); 该接口,只有一个方法,需要实现.该方法表示事件发生时,返回需要被通知的Watcher集合,可能为空集合. ZKWatchManager 1.ZKWatchManager是ZooKeep