ZooKeeper源码阅读系列-zk的Watcher机制一

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 MSE Higress,422元/月
简介: 原计划今天是安利好用的开源框架系列,但是最近被赶鸭子'上线',开源软件篇还没有写完,就继续源码解读。 ZooKeeper是使用得最频繁的分布式框架了,一直都感觉它功能强大,貌似无所不能,能当注册中心也能当分布式锁,那它的底层究竟是怎么设计和运行的,我也一直很好奇,所以今天来研究一下,zk的wather机制,篇幅会较长所以会分就几个章节进行解读。

微信截图_20220531131804.png

前言

原计划今天是安利好用的开源框架系列,但是最近被赶鸭子'上线',开源软件篇还没有写完,就继续源码解读。 ZooKeeper是使用得最频繁的分布式框架了,一直都感觉它功能强大,貌似无所不能,能当注册中心也能当分布式锁,那它的底层究竟是怎么设计和运行的,我也一直很好奇,所以今天来研究一下,zk的wather机制,篇幅会较长所以会分就几个章节进行解读。

ZooKeeper的Watcher机制,总的来说可以分为三个过程:
1. 客户端注册Watcher
2. 服务器处理Watcher
3. 客户端回调Watcher

整个过程涉及到的类图如下图所示: 微信截图_20220531132040.png包含以下主要的方法和类:

1.Zookeeper:客户端的Main.class
2.ClientWatchManager:接口,表示客户端的Watcher管理者,其定义了materialized方法,需子类实现。
3.ZKWatchManager:Zookeeper的内部类,ClientWatchManager的实现类。
4.WatchRegistration: watcher的注册包装类。
5.ClientCnxn:客户端核心线程管理类。
6.Packet:client和server的通信协议。
首先我们看下Watch在Client的存储以及体现以及主要涉及到的类
Watcher:接口类型,其定义了process方法,需子类实现。
Event:接口类型,Watcher的内部类,无任何方法。
KeeperState:枚举类型,Event的内部类,表示Zookeeper所处的状态。
EventType:枚举类型,Event的内部类,表示Zookeeper中发生的事件类型。
WatchedEvent:表示对ZooKeeper上发生变化后的反馈,包含了KeeperState和EventType。
ClientWatchManager:接口类型,表示客户端的Watcher管理者,其定义了materialized方法,需子类实现。
复制代码

在看之前要明白一个事情,Watcher是什么? ZK中引入Watcher机制来实现分布式的通知功能。 ZK允许客户端向服务端注册一个Watcher监听,当服务点的的指定事件触发监听时,那么服务端就会向客户端发送事件通知,以便客户端完成逻辑操作(即客户端向服务端注册监听,并将Watcher对象存在客户端的Watchermanager中服务端触发事件后,向客户端发送通知,客户端收到通知后从wacherManager中取出对象来执行回调逻辑) watcher的特点: 1.一次性:一旦一个Watcher被触发,ZK都会将其从相应的的存储中移除,所以Watcher是需要每注册一次,才可触发一次。 2. 客户端串行执行:客户端Watcher回调过程是一个串行同步的过程。 3. 轻量:Watcher数据结构中只包含:通知状态、事件类型和节点路径 接下来看看Watcher的类图: 微信截图_20220531132113.pngwatcher的源码解读

public interface Watcher {
    public interface Event {
     //用于记录Event发生时的zk状态(通知状态)
        public enum KeeperState { 
            @Deprecated
            //未知状态
            Unknown (-1),
            //客户端和服务端断开状态
            Disconnected (0), 
            @Deprecated
            //未同步链接
            NoSyncConnected (1),
             //客户端和服务端处于连接状态
            SyncConnected (3),
            //权限验证异常
            AuthFailed (4), 
             //只读
            ConnectedReadOnly (5),
            //SASL认证通过状态
            SaslAuthenticated(6),
            //会话过期
            Expired (-112);
         //省略......
         //用于记录event的类型
        public enum EventType {
            None (-1),
            NodeCreated (1),
            NodeDeleted (2),
            NodeDataChanged (3),
            NodeChildrenChanged (4);
            private final int intValue;
            public static EventType fromInt(int intValue) {
                switch(intValue) {
                 //客户端和服务器成功建立连接
                    case -1: return EventType.None;     
                    //watch监听对应节点被创建
                    case  1: return EventType.NodeCreated;
                    //watch 对应节点删除
                    case  2: return EventType.NodeDeleted;
                     // 监听对应节点数据内容发生改变
                    case  3: return EventType.NodeDataChanged;
                    /监听对应节点的子节点列表发生变化
                    case  4: return EventType.NodeChildrenChanged;/
                    default:
                        throw new RuntimeException("Invalid integer value for conversion to EventType");
                }
            }
        }
    }
    ////回调函数实现该函数,表示根据event执行的行为
    abstract public void process(WatchedEvent event);
}
复制代码
Watcher的类总结:
1. process函数,用于处理回调
2. 内部类Event又包含内部类KeeperState以及EventType
3. KeeperState用于记录Event发生时的zk状态(通知状态)
4. EventType用于记录Event的类型

接着看下WatchedEvent类,WatchedEvent三个属性很好的体现了这个类的意思记录了哪个节点,zk的状态以及影响的事件类型,代码如下:

public class WatchedEvent {
    //zk服务的状态
    final private KeeperState keeperState; 
    //事件类型
    final private EventType eventType; 
    //节点的路径
    private String path; 
    //转换为WatcherEvent
    public WatcherEvent getWrapper() {
        return new WatcherEvent(eventType.getIntValue(),
                keeperState.getIntValue(),
                path);
    }
}
复制代码

接着就是Watcher在Client存储的核心类ClientWatchManager接口的实现类ZKWatchManager,该方法在事件发生后,返回需要被通知的Watcher集合。在该方法中,首先会根据EventType类型确定相应的事件类型,然后根据事件类型的不同做出相应的操作,如针对None类型,即无任何事件,则首先会从三个键值对中删除clientPath对应的Watcher,然后将剩余的Watcher集合添加至结果集合;针对NodeDataChanged和NodeCreated事件而言,其会从dataWatches和existWatches中删除clientPath对应的Watcher,然后将剩余的Watcher集合添加至结果集合,从这个方法中也可看到Watcher的一次性,执行一次都删除了。

小结: 上面的类图画得有点丑,大家凑合看吧,还不太习惯画图,另外源码解读的也可能存在不到位或者理解错误的地方,还是得多看几遍代码。

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
目录
相关文章
|
5月前
|
监控 NoSQL Java
分布式锁实现原理问题之ZooKeeper的观察器(Watcher)特点问题如何解决
分布式锁实现原理问题之ZooKeeper的观察器(Watcher)特点问题如何解决
|
2月前
|
分布式计算 Java Hadoop
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
70 1
|
2月前
|
分布式计算 监控 Hadoop
Hadoop-29 ZooKeeper集群 Watcher机制 工作原理 与 ZK基本命令 测试集群效果 3台公网云服务器
Hadoop-29 ZooKeeper集群 Watcher机制 工作原理 与 ZK基本命令 测试集群效果 3台公网云服务器
45 1
|
2月前
|
分布式计算 Hadoop Unix
Hadoop-28 ZooKeeper集群 ZNode简介概念和测试 数据结构与监听机制 持久性节点 持久顺序节点 事务ID Watcher机制
Hadoop-28 ZooKeeper集群 ZNode简介概念和测试 数据结构与监听机制 持久性节点 持久顺序节点 事务ID Watcher机制
51 1
|
4月前
|
监控 API
【zookeeper 第四篇章】监控 Watcher
ZooKeeper通过Watcher机制实现了数据的发布/订阅功能。多个订阅者可以监听同一主题对象,一旦该对象状态变化,如节点内容或子节点列表变动,ZooKeeper会实时通知所有订阅者。Watcher架构包括ZooKeeper服务端、客户端及其Watcher管理器。客户端向服务端注册Watcher并保存至本地管理器中;当状态变化时,服务端通知客户端,触发相关Watcher回调处理逻辑。
88 2
|
5月前
|
存储 数据库
zookeeper 集群环境搭建及集群选举及数据同步机制
zookeeper 集群环境搭建及集群选举及数据同步机制
99 2
|
5月前
|
API
【想进大厂还不会阅读源码】ShenYu源码-替换ZooKeeper客户端
ShenYu源码阅读。相信大家碰到源码时经常无从下手,不知道从哪开始阅读😭。我认为有一种办法可以解决大家的困扰!至此,我们发现自己开始从大量堆砌的源码中脱离开来😀。ShenYu是一个异步的,高性能的,跨语言的,响应式的 API 网关。
|
7月前
|
网络协议 中间件 数据库
Zookeeper学习系列【三】Zookeeper 集群架构、读写机制以及一致性原理(ZAB协议)
Zookeeper学习系列【三】Zookeeper 集群架构、读写机制以及一致性原理(ZAB协议)
282 0
|
7月前
|
存储 API
深入理解Zookeeper系列-4.Watcher原理
深入理解Zookeeper系列-4.Watcher原理
60 1
|
3月前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
下一篇
DataWorks