美文网首页
Watcher---Zk事件监听机制和原理

Watcher---Zk事件监听机制和原理

作者: 名字是乱打的 | 来源:发表于2020-04-05 15:28 被阅读0次

    Zookeeper的Watcher 监听机制是 Zookeeper 中非常重要的特性,很多时候我们之所以用Zookeeper的原因其实都是因为Zookeeper这个特性.

    想一想,我其实很久之前貌似做过类似于持续集成自动配置方面的尝试,那时候好像用的是MQ,我的配置改变了后向MQ发个消息,然后客户端的MQ消费者重新拉配置下来进行更新...


    一. Zookeeper事件监听机制

    我们基于 zookeeper 上创建的节点,可以对这些节点绑定监听事件,比如可以监听节点数据变更、节点删除、子节点状态变更等事件,通过这个事件机制,可以基于 zookeeper实现分布式锁集群管理等功能

    watcher 特性当数据发生变化的时候, zookeeper 会产生\color{red}{一个} watcher 事件,并且会发送到客户端。但是客户端只会收到\color{red}{一次}通知。如果后续这个节点再次发生变化,那么之前设置 watcher 的客户端不会再次收到消息。(watcher 是一次性的操作)。 \color{red}{可以通过循环监听去达到永久监听效果.}

    二 .如何绑定事件机制呢?

    以下三个方法均可在使用时候绑定事件.

    • getData
    • Exists
    • getChildren
    那么哪些操作会触发事件呢?

    如何触发事件? 凡是事务类型的操作,都会触发监听事件。
    其实也就是create /delete /setData

    三 watcher 事件类型

    • None (-1), 客户端链接状态发生变化的时候,会收到 none 的事件
    • NodeCreated (1), 创建节点的事件。
    • NodeDeleted (2), 删除节点的事件
    • NodeDataChanged (3), 节点数据发生变更
    • NodeChildrenChanged (4); 子节点被创建、被删除、会发生事件触发

    举个栗子

    private static void addEvent(String path) throws KeeperException, InterruptedException {
            zooKeeper.exists(path, new Watcher(){
                @Override
                public void process(WatchedEvent watchedEvent) {
                    System.out.println("触发事件机制的路径为:"+watchedEvent.getPath());
                    System.out.println("事件类型为:"+watchedEvent.getType());
                }
            });
        }
    
    结果如下图,这也体现了事件的一次性性质,我们明明改变了两次却只触发了一次.

    根据人家ZK文档,这里我们加入循环试试,我在添加事件机制在结束的时候,我又再次的为/test结点添加了事件

       private static void addEvent(String path) throws KeeperException, InterruptedException {
            zooKeeper.exists(path, new Watcher(){
                @Override
                public void process(WatchedEvent watchedEvent) {
                    System.out.println("触发事件机制的路径为:"+watchedEvent.getPath());
                    System.out.println("事件类型为:"+watchedEvent.getType());
                    //再次为该结点绑定监听,使监听机制有效
                    try {
                        zooKeeper.exists(watchedEvent.getPath(),true);
                    } catch (KeeperException e) {
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    

    但是结果如下,我们还是没有监听到事件


    那么问题出在哪里呢?实际上,我们在zooKeeper.exists(watchedEvent.getPath(),true);开启的不是exits里自添加的事件,而是走的默认全局事件,我们在创建结点时候添加了一个事件
    这里我们验证一下,添加一个全局事件打印
    结果如下,验证了我们的猜想

    各种操作对应的事件类型


    二 . Zookeeper的实现原理

    关于watcher事件监听机制,客户端与服务器的大致协调.服务器会受到客户端的命令,使服务器知道哪些Znode开启了事件

    watcher源码流程:

    源码大致流程

    具体源码分析:

    首先找到我们添加事件监听机制的方法,比如exists
    唤醒触发机制

    上面的源码分析我们发现我们只是添加了监听事件的入队,那么出队的消费呢?在哪?

    回头我们看一下Zookeeper的构造方法 发现里面启动了俩线程
    还有一些判断比如to判断心跳问题
    很多很多的判断之后发现最后发现一切正常后,调用传输socket 不论是我们用NIO还是Netty,其消费都是差不多的.我们以Netty为例看下源码.
    DoWrite 方法

    sendPkt



    到此ZK监听机制的客户端部分分析完成!

    关于ZK服务器端的watcher机制分析.

    跟着某大佬提供的服务端接收请求处理流程总流程,我们看看源码

    服务端接收请求处理流程

    以后再分析服务端,现在写论文去了.....

    相关文章

      网友评论

          本文标题:Watcher---Zk事件监听机制和原理

          本文链接:https://www.haomeiwen.com/subject/pytephtx.html