zookeeper-事件监听机制(3)

zookeeper事件监听机制

  • watcher机制:

​ zookeeper提供了数据的发布/订阅功能,多个订阅者可同时监听某一特定主题对象,当该主题对象的自身状态发生变化时(例如节点内容改变、节点下的子节点列表改变 等),会实时、主动通知所有订阅者

​ zookeeper采用了Watcher机制实现数据的发布/订阅功能。该机制在被订阅对象发生变化时会异步通知客户端,因此客户端不必在Watcher注册后轮询阻塞,从而减轻了客户端压力

  • watcher模型:

    客户端首先将watcher注册到zk服务端,同时将watcher对象保存在客户端的watcher管理器中,zk的服务端监听到数据的变化后,通知客户端,客户端的watcher管理器触发相关的watcher来回调来处理逻辑,完成整体的发布/订阅流程

  • watcher特性

    • 一次性

      watcher是一次性的,一旦被触发就会移除,再次使用时需要重新注册

    • 轻量级

      WatchEvent是最小的通信单元,结构上只包含通知状态、事件类型和节点 路径,并不会告诉数据节点变化前后的具体内容;

    • 客户端顺序回调

      watcher回调是顺序串行化执行的,只有回调后客户端才能看到最新的数 据状态。一个watcher回调逻辑不应该太多,以免影响别的watcher执行

    • 时效性

      watcher只有在当前session彻底失效时才会无效,若在session有效期内快速重连成功,则watcher依然存在,仍可接收到通知

  • watcher接口

    Watcher是一个接口,任何实现了Watcher接口的类就是一个新的Watcher。

    Watcher内部包含了两个枚举类:KeeperState、EventType

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M8yCiNSs-1585660091783)(E:/Typora/typora-user-images/18300896-0cf1d1fd914f0a1e.webp)]

  • Watcher通知状态**(KeeperState)**

KeeperState是客户端与服务端连接状态发生变化时对应的通知类型

枚举属性 说明
SyncConnected 客户端与服务器正常连接时
Disconnected 客户端与服务器断开连接时
Expired 会话session失效时
AuthFailed 身份认证失败时
  • Watcher事件类型**(EventType)**

EventType是数据节点(znode)发生变化时对应的通知类型

EventType变化时,KeeperState永远处于SyncConnected通知状态下;当KeeperState发生变化时, EventType永远为None。

枚举属性 说明
None
NodeCreated Watcher监听的数据节点被创建时
NodeDeleted Watcher监听的数据节点被删除时
NodeDataChanged Watcher监听的数据节点内容发生变更时(无论内容数据是否变化)
NodeChildrenChanged Watcher监听的数据节点的子节点列表发生变更时

客户端接收到的相关事件通知中只包含状态及类型等信息,不包括节点变化前后的具体内容,变化前的数据需业务自身存储,变化后的数据需调用get等方法重新获取

  • 捕获相应的事件

在zookeeper中采用

zk.exists(path, watch)zk.getData(path, watcher, stat)zk.getChildren(path, watch)

这样的方式为某个znode注册监听

注册方式 created childrenchanged changed delete
zk.exists(path, watch) 可监控 可监控 可监控
zk.getData(path, watcher, stat) 可监控 可监控
zk.getChildren(path, watch) 可监控 可监控
  • 客户端和服务端连接状态实现demo
/**
 * @Author: zxx
 * @Date: 2020/3/29 22:05
 * @Description: watcher机制
 * 通知状态 KeeperState:
 * SyncConnected:客户端与服务器正常连接时
 * Disconnected:客户端与服务器断开连接时
 * Expired:会话session失效时
 * AuthFailed:身份认证失败时
 * 
 * 事件类型 EventType none
 */
public class ZKConnectWatcher implements Watcher {
    // 计数器对象
    public static CountDownLatch countDownLatch=new CountDownLatch(1);
    // 连接对象
    public static ZooKeeper zooKeeper;

    public void process(WatchedEvent watchedEvent) {
        try {
            //EventType = None时
            if (watchedEvent.getType() == Event.EventType.None){
                if (watchedEvent.getState() == Event.KeeperState.SyncConnected){
                    System.out.println("连接成功");
                    countDownLatch.countDown();
                }else if (watchedEvent.getState() == Event.KeeperState.Disconnected){
                    System.out.println("断开连接");
                }else if (watchedEvent.getState() == Event.KeeperState.Expired){
                    System.out.println("会话超时");
                }else if (watchedEvent.getState() == Event.KeeperState.AuthFailed){
                    System.out.println("认证失败");
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        try {
            zooKeeper=new ZooKeeper("192.168.21.141:2181", 5000, new ZKConnectWatcher());
            // 阻塞线程等待连接的创建
            countDownLatch.await();
            // 会话id
            System.out.println(zooKeeper.getSessionId());
            Thread.sleep(50000);
            zooKeeper.close(); 
            System.out.println("结束");
        } catch (Exception e) {
            e.printStackTrace();
        }
        }
    }

  • 检查节点是否存在

/**
 * @Author: zxx
 * @Date: 2020/3/30 19:57
 * @Description: zk.exists(“/node- x”,watcher)
 */
public class ZKWatcherExists {

    private String IP = "192.168.60.130:2181";

    public static ZooKeeper zooKeeper;

    //连接zookeeper
    @Before
    public void before() throws InterruptedException, IOException {
       final CountDownLatch countDownLatch=new CountDownLatch(1);
       zooKeeper = new ZooKeeper(IP, 6000, new Watcher() {
           public void process(WatchedEvent watchedEvent) {
               if (watchedEvent.getState() == Event.KeeperState.SyncConnected){
                   countDownLatch.countDown();
               }
               System.out.println("path=" + watchedEvent.getPath());
               System.out.println("eventType=" + watchedEvent.getType());
           }
       });
       countDownLatch.await();
    }

    @After
    public void after() throws InterruptedException {
        zooKeeper.close();
    }

    @Test
    public void watcherExists1() throws KeeperException, InterruptedException {
        // arg1:节点的路径
        // arg2:使用连接对象中的watcher
        zooKeeper.exists("/watcher1", true);
        Thread.sleep(50000);
        System.out.println("结束");
    }

    @Test
    public void watcherExists2() throws KeeperException, InterruptedException {
        Watcher watcher = new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                System.out.println("自定义watcher");
                System.out.println("path=" + watchedEvent.getPath());
                System.out.println("eventType=" + watchedEvent.getType());
            }};

        zooKeeper.exists("/watcher1", watcher);
        Thread.sleep(50000);
        System.out.println("结束");
    }

    @Test
    public void watcherExists3() throws KeeperException, InterruptedException {
        // arg1:节点的路径
        // arg2:使用连接对象中的watcher
        zooKeeper.exists("/watcher1", new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                System.out.println("自定义watcher");
                System.out.println("path=" + watchedEvent.getPath());
                System.out.println("eventType=" + watchedEvent.getType());
            }
        });
        Thread.sleep(50000);
        System.out.println("结束");
    }

    @Test
    public void watcherExists4() throws KeeperException, InterruptedException {
        zooKeeper.exists("/watcher1", new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                System.out.println("自定义watcher1");
                System.out.println("path=" + watchedEvent.getPath());
                System.out.println("eventType=" + watchedEvent.getType());
            }
        });
        zooKeeper.exists("/watcher1", new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                System.out.println("自定义watcher2");
                System.out.println("path=" + watchedEvent.getPath());
                System.out.println("eventType=" + watchedEvent.getType());
            }
        });
        Thread.sleep(50000);
        System.out.println("结束");
    }
}

  • 查看节点

/**
 * @Author: zxx
 * @Date: 2020/3/30 19:57
 * @Description: zk.getData(path, watcher, stat)
 */
public class ZKWatcherGetData {

    private String IP = "192.168.60.130:2181";

    public static ZooKeeper zooKeeper;

    //连接zookeeper
    @Before
    public void before() throws InterruptedException, IOException {
       final CountDownLatch countDownLatch=new CountDownLatch(1);
       zooKeeper = new ZooKeeper(IP, 6000, new Watcher() {
           public void process(WatchedEvent watchedEvent) {
               if (watchedEvent.getState() == Event.KeeperState.SyncConnected){
                   countDownLatch.countDown();
               }
               System.out.println("path=" + watchedEvent.getPath());
               System.out.println("eventType=" + watchedEvent.getType());
           }
       });
       countDownLatch.await();
    }

    @After
    public void after() throws InterruptedException {
        zooKeeper.close();
    }

    @Test
    public void watcherGetData1() throws KeeperException, InterruptedException {
        // arg1:节点的路径
        // arg2:使用连接对象中的watcher
        zooKeeper.getData("/watcher1", true,null);
        Thread.sleep(50000);
        System.out.println("结束");
    }

    @Test
    public void watcherGetData2() throws KeeperException, InterruptedException {
        Watcher watcher = new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                System.out.println("自定义watcher");
                System.out.println("path=" + watchedEvent.getPath());
                System.out.println("eventType=" + watchedEvent.getType());
            }};
        zooKeeper.getData("/watcher1", watcher,null);
        Thread.sleep(50000);
        System.out.println("结束");
    }

    @Test
    public void watcherGetData3() throws KeeperException, InterruptedException {
        // arg1:节点的路径
        // arg2:使用连接对象中的watcher
        zooKeeper.getData("/watcher1", new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                System.out.println("自定义watcher");
                System.out.println("path=" + watchedEvent.getPath());
                System.out.println("eventType=" + watchedEvent.getType());
            }
        },null);
        Thread.sleep(50000);
        System.out.println("结束");
    }

    @Test
    public void watcherGetData4() throws KeeperException, InterruptedException {
        zooKeeper.getData("/watcher1", new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                System.out.println("自定义watcher1");
                System.out.println("path=" + watchedEvent.getPath());
                System.out.println("eventType=" + watchedEvent.getType());
            }
        },null);
        zooKeeper.getData("/watcher1", new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                System.out.println("自定义watcher2");
                System.out.println("path=" + watchedEvent.getPath());
                System.out.println("eventType=" + watchedEvent.getType());
            }
        },null);
        Thread.sleep(50000);
        System.out.println("结束");
    }
}

  • 查看子节点

/**
 * @Author: zxx
 * @Date: 2020/3/30 19:57
 * @Description: zk.getChildren(path, watch)**
 */
public class ZKWatcherGetChildren {

    private String IP = "192.168.60.130:2181";

    public static ZooKeeper zooKeeper;

    //连接zookeeper
    @Before
    public void before() throws InterruptedException, IOException {
       final CountDownLatch countDownLatch=new CountDownLatch(1);
       zooKeeper = new ZooKeeper(IP, 6000, new Watcher() {
           public void process(WatchedEvent watchedEvent) {
               if (watchedEvent.getState() == Event.KeeperState.SyncConnected){
                   countDownLatch.countDown();
               }
               System.out.println("path=" + watchedEvent.getPath());
               System.out.println("eventType=" + watchedEvent.getType());
           }
       });
       countDownLatch.await();
    }

    @After
    public void after() throws InterruptedException {
        zooKeeper.close();
    }

    @Test
    public void watcherGetChildren1() throws KeeperException, InterruptedException {
        // arg1:节点的路径
        // arg2:使用连接对象中的watcher
        zooKeeper.getChildren("/watcher1", true);
        Thread.sleep(50000);
        System.out.println("结束");
    }

    @Test
    public void watcherGetChildren2() throws KeeperException, InterruptedException {
        Watcher watcher = new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                System.out.println("自定义watcher");
                System.out.println("path=" + watchedEvent.getPath());
                System.out.println("eventType=" + watchedEvent.getType());
            }};
        zooKeeper.getChildren("/watcher1", watcher);
        Thread.sleep(50000);
        System.out.println("结束");
    }

    @Test
    public void watcherGetChildren3() throws KeeperException, InterruptedException {
        zooKeeper.getChildren("/watcher1", new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                System.out.println("自定义watcher");
                System.out.println("path=" + watchedEvent.getPath());
                System.out.println("eventType=" + watchedEvent.getType());
            }
        });
        Thread.sleep(50000);
        System.out.println("结束");
    }

    @Test
    public void watcherGetChildren4() throws KeeperException, InterruptedException {
        zooKeeper.getChildren("/watcher1", new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                System.out.println("自定义watcher1");
                System.out.println("path=" + watchedEvent.getPath());
                System.out.println("eventType=" + watchedEvent.getType());
            }
        });
        zooKeeper.getChildren("/watcher1", new Watcher() {
            public void process(WatchedEvent watchedEvent) {
                System.out.println("自定义watcher2");
                System.out.println("path=" + watchedEvent.getPath());
                System.out.println("eventType=" + watchedEvent.getType());
            }
        });
        Thread.sleep(50000);
        System.out.println("结束");
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章