设为首页 收藏本站
查看: 948|回复: 0

[经验分享] zookeeper client分析

[复制链接]

尚未签到

发表于 2017-4-18 13:33:47 | 显示全部楼层 |阅读模式
  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处理

  •   计算selecttimeout(上面提到的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模式

        


  


用户评论

暂无评论。

发表评论:提交

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-366004-1-1.html 上篇帖子: Zookeeper 分布式配置管理 下篇帖子: 待整理ZooKeeper-资源收集
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表