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

[经验分享] Zookeeper全解析——Client端

[复制链接]

尚未签到

发表于 2019-1-9 06:25:53 | 显示全部楼层 |阅读模式
  Zookeeper的Client直接与用户打交道,是我们使用Zookeeper的
interface。了解ZK Client的结构和工作原理有利于我们合理的使用ZK,并能在使用中更早的发现问题。本文将在研究源码的技术上讲述ZKClient的工作原理及内部工作机制。
  在看完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 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()里面完成:

    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/



运维网声明 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-660894-1-1.html 上篇帖子: Paxos算法之旅(四)zookeeper代码解析 下篇帖子: 微服务分布式企业框架mybatis+shiro+Dubbo+Springmvc++ZooKeeper
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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