46-微服务技术栈(高级):分布式协调服务zookeeper源码篇(Watcher机制-1)

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
简介:   前面已经分析了Zookeeper持久话相关的类,下面接着分析Zookeeper中的Watcher机制所涉及到的类。

一、前言

  前面已经分析了Zookeeper持久话相关的类,下面接着分析Zookeeper中的Watcher机制所涉及到的类。

二、总体框图

  对于Watcher机制而言,主要涉及的类主要如下。

  

说明:

Watcher

接口类型,其定义了process方法,需子类实现

Event

接口类型,Watcher的内部类,无任何方法

KeeperState

枚举类型,Event的内部类,表示Zookeeper所处的状态

EventType

枚举类型,Event的内部类,表示Zookeeper中发生的事件类型

WatchedEvent

表示对ZooKeeper上发生变化后的反馈,包含了KeeperState和EventType

ClientWatchManager

接口类型,表示客户端的Watcher管理者,其定义了materialized方法,需子类实现

ZKWatchManager

Zookeeper的内部类,继承ClientWatchManager

MyWatcher

ZooKeeperMain的内部类,继承Watcher

ServerCnxn

接口类型,继承Watcher,表示客户端与服务端的一个连接

WatchManager

管理Watcher

三、Watcher源码分析

3.1 内部类

  Event,接口类型,表示事件代表的状态,除去其内部类,其源码结构如下

public interface Watcher {


   public interface Event {

       /**

        * Enumeration of states the ZooKeeper may be at the event

        */

       public enum KeeperState {


           @Deprecated

           Unknown (-1),


           Disconnected (0),


           @Deprecated

           NoSyncConnected (1),


           SyncConnected (3),


           AuthFailed (4),


           ConnectedReadOnly (5),


           SaslAuthenticated(6),


           Expired (-112);


           private final int intValue;    


           KeeperState(int intValue) {

               this.intValue = intValue;

           }


           public int getIntValue() {

               return intValue;

           }


           public static KeeperState fromInt(int intValue) {

               switch(intValue) {

                   case   -1: return KeeperState.Unknown;

                   case    0: return KeeperState.Disconnected;

                   case    1: return KeeperState.NoSyncConnected;

                   case    3: return KeeperState.SyncConnected;

                   case    4: return KeeperState.AuthFailed;

                   case    5: return KeeperState.ConnectedReadOnly;

                   case    6: return KeeperState.SaslAuthenticated;

                   case -112: return KeeperState.Expired;


                   default:

                       throw new RuntimeException("Invalid integer value for conversion to KeeperState");

               }

           }

       }


       /**

        * Enumeration of types of events that may occur on the ZooKeeper

        */

       public enum EventType {

           None (-1),

           NodeCreated (1),

           NodeDeleted (2),

           NodeDataChanged (3),

           NodeChildrenChanged (4);


           private final int intValue;    


           EventType(int intValue) {

               this.intValue = intValue;

           }


           public int getIntValue() {

               return intValue;

           }


           public static EventType fromInt(int intValue) {

               switch(intValue) {

                   case -1: return EventType.None;

                   case  1: return EventType.NodeCreated;

                   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接口并没有定义任何属性和方法,但其包含了KeeperState和EventType两个内部枚举类。

可以简化成:

public interface Event {}

3.2 接口方法  

abstract public void process(WatchedEvent event);

说明:其代表了实现Watcher接口时必须实现的的方法,即定义进行处理,WatchedEvent表示观察的事件。

四、Event源码分析(即3.1内部类)

4.1 内部类

1. KeeperState 

public enum KeeperState { // 事件发生时Zookeeper的状态

   /** Unused, this state is never generated by the server */

   @Deprecated

   // 未知状态,不再使用,服务器不会产生此状态

   Unknown (-1),


   /** The client is in the disconnected state - it is not connected

   * to any server in the ensemble. */

   // 断开

   Disconnected (0),


   /** Unused, this state is never generated by the server */

   @Deprecated

   // 未同步连接,不再使用,服务器不会产生此状态

   NoSyncConnected (1),


   /** The client is in the connected state - it is connected

   * to a server in the ensemble (one of the servers specified

   * in the host connection parameter during ZooKeeper client

   * creation). */

   // 同步连接状态

   SyncConnected (3),


   /**

   * Auth failed state

   */

   // 认证失败状态

   AuthFailed (4),


   /**

   * The client is connected to a read-only server, that is the

   * server which is not currently connected to the majority.

   * The only operations allowed after receiving this state is

   * read operations.

   * This state is generated for read-only clients only since

   * read/write clients aren't allowed to connect to r/o servers.

   */

   // 只读连接状态

   ConnectedReadOnly (5),


   /**

   * SaslAuthenticated: used to notify clients that they are SASL-authenticated,

   * so that they can perform Zookeeper actions with their SASL-authorized permissions.

   */

   // SASL认证通过状态

   SaslAuthenticated(6),


   /** The serving cluster has expired this session. The ZooKeeper

   * client connection (the session) is no longer valid. You must

   * create a new client connection (instantiate a new ZooKeeper

   * instance) if you with to access the ensemble. */

   // 过期状态

   Expired (-112);


   // 代表状态的整形值

   private final int intValue;     // Integer representation of value

   // for sending over wire



   // 构造函数

   KeeperState(int intValue) {

       this.intValue = intValue;

   }


   // 返回整形值

   public int getIntValue() {

       return intValue;

   }


   // 从整形值构造相应的状态

   public static KeeperState fromInt(int intValue) {

       switch(intValue) {

           case   -1: return KeeperState.Unknown;

           case    0: return KeeperState.Disconnected;

           case    1: return KeeperState.NoSyncConnected;

           case    3: return KeeperState.SyncConnected;

           case    4: return KeeperState.AuthFailed;

           case    5: return KeeperState.ConnectedReadOnly;

           case    6: return KeeperState.SaslAuthenticated;

           case -112: return KeeperState.Expired;


           default:

               throw new RuntimeException("Invalid integer value for conversion to KeeperState");

       }

   }

}

说明:KeeperState是一个枚举类,其定义了在事件发生时Zookeeper所处的各种状态,其还定义了一个从整形值返回对应状态的方法fromInt。

2. EventType 

public enum EventType { // 事件类型

   // 无

   None (-1),

   // 结点创建

   NodeCreated (1),

   // 结点删除

   NodeDeleted (2),

   // 结点数据变化

   NodeDataChanged (3),

   // 结点子节点变化

   NodeChildrenChanged (4);


   // 代表事件类型的整形

   private final int intValue;     // Integer representation of value

   // for sending over wire


   // 构造函数

   EventType(int intValue) {

       this.intValue = intValue;

   }


   // 返回整形

   public int getIntValue() {

       return intValue;

   }


   // 从整形构造相应的事件

   public static EventType fromInt(int intValue) {

       switch(intValue) {

           case -1: return EventType.None;

           case  1: return EventType.NodeCreated;

           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");

       }

   }          

}

说明:EventType是一个枚举类,其定义了事件的类型(如创建节点、删除节点等事件),同时,其还定义了一个从整形值返回对应事件类型的方法fromInt。

五、WatchedEvent

5.1 类的属性 

public class WatchedEvent {

   // Zookeeper的状态

   final private KeeperState keeperState;

   // 事件类型

   final private EventType eventType;

   // 事件所涉及节点的路径

   private String path;

}

说明:WatchedEvent类包含了三个属性,分别代表事件发生时Zookeeper的状态、事件类型和发生事件所涉及的节点路径。

5.2 构造函数

  1. public WatchedEvent(EventType eventType, KeeperState keeperState, String path)型构造函数 

public WatchedEvent(EventType eventType, KeeperState keeperState, String path) {

   // 初始化属性

   this.keeperState = keeperState;

   this.eventType = eventType;

   this.path = path;

}

  说明:构造函数传入了三个参数,然后分别对属性进行赋值操作。

  2. public WatchedEvent(WatcherEvent eventMessage)型构造函数  

public WatchedEvent(WatcherEvent eventMessage) {

   // 从eventMessage中取出相应属性进行赋值

   keeperState = KeeperState.fromInt(eventMessage.getState());

   eventType = EventType.fromInt(eventMessage.getType());

   path = eventMessage.getPath();

}

  说明:构造函数传入了WatcherEvent参数,之后直接从该参数中取出相应属性进行赋值操作。

五总结:对于WatchedEvent类的方法而言,相对简单,包含了几个getXXX方法,用于获取相应的属性值。

六、ClientWatchManager

public Set<Watcher> materialize(Watcher.Event.KeeperState state,

                               Watcher.Event.EventType type, String path);

  说明:该方法表示事件发生时,返回需要被通知的Watcher集合,可能为空集合。

七、ZKWatchManager(zookeeper内)

7.1 类的属性

private static class ZKWatchManager implements ClientWatchManager {

   

   // 数据变化的Watchers

   private final Map<String, Set<Watcher>> dataWatches = new HashMap<String, Set<Watcher>>();

   

   // 节点存在与否的Watchers

   private final Map<String, Set<Watcher>> existWatches = new HashMap<String, Set<Watcher>>();

   

   // 子节点变化的Watchers

   private final Map<String, Set<Watcher>> childWatches = new HashMap<String, Set<Watcher>>();

}

 说明:ZKWatchManager实现了ClientWatchManager,并定义了三个Map键值对,键为节点路径,值为Watcher。分别对应数据变化的Watcher、节点是否存在的Watcher、子节点变化的Watcher。

7.2 核心方法分析

1. materialize方法

public Set<Watcher> materialize(Watcher.Event.KeeperState state,

                               Watcher.Event.EventType type,

                               String clientPath)

{

   // 新生成结果Watcher集合

   Set<Watcher> result = new HashSet<Watcher>();


   switch (type) { // 确定事件类型

       case None: // 无类型

           // 添加默认Watcher

           result.add(defaultWatcher);

           // 是否需要清空(提取对zookeeper.disableAutoWatchReset字段进行配置的值、

           // Zookeeper的状态是否为同步连接)

           boolean clear = ClientCnxn.getDisableAutoResetWatch() &&

               state != Watcher.Event.KeeperState.SyncConnected;

  // 同步块

           synchronized(dataWatches) {

               for(Set<Watcher> ws: dataWatches.values()) {

                   // 添加至结果集合

                   result.addAll(ws);

               }

               if (clear) { // 是否需要清空

                   dataWatches.clear();

               }

           }

           // 同步块

           synchronized(existWatches) {  

               for(Set<Watcher> ws: existWatches.values()) {

                   // 添加至结果集合

                   result.addAll(ws);

               }

               if (clear) { // 是否需要清空

                   existWatches.clear();

               }

           }

           

  // 同步块

           synchronized(childWatches) {

               for(Set<Watcher> ws: childWatches.values()) {

                   // 添加至结果集合

                   result.addAll(ws);

               }

               if (clear) { // 是否需要清空

                   childWatches.clear();

               }

           }

           // 返回结果

           return result;

       case NodeDataChanged: // 节点数据变化

       case NodeCreated: // 创建节点

           synchronized (dataWatches) { // 同步块

               // 移除clientPath对应的Watcher后全部添加至结果集合

               addTo(dataWatches.remove(clientPath), result);

           }

           synchronized (existWatches) {

               // 移除clientPath对应的Watcher后全部添加至结果集合

               addTo(existWatches.remove(clientPath), result);

           }

           break;

       case NodeChildrenChanged: // 节点子节点变化

           synchronized (childWatches) {

               // 移除clientPath对应的Watcher后全部添加至结果集合

               addTo(childWatches.remove(clientPath), result);

           }

           break;

       case NodeDeleted: // 删除节点

           synchronized (dataWatches) {

               // 移除clientPath对应的Watcher后全部添加至结果集合

               addTo(dataWatches.remove(clientPath), result);

           }

           // XXX This shouldn't be needed, but just in case

           synchronized (existWatches) {

               // 移除clientPath对应的Watcher

               Set<Watcher> list = existWatches.remove(clientPath);

               if (list != null) {

                   // 移除clientPath对应的Watcher后全部添加至结果集合

                   addTo(existWatches.remove(clientPath), result);

                   LOG.warn("We are triggering an exists watch for delete! Shouldn't happen!");

               }

           }

           synchronized (childWatches) {

               // 移除clientPath对应的Watcher后全部添加至结果集合

               addTo(childWatches.remove(clientPath), result);

           }

           break;

       default: // 缺省处理

           String msg = "Unhandled watch event type " + type

               + " with state " + state + " on path " + clientPath;

           LOG.error(msg);

           throw new RuntimeException(msg);

   }


   // 返回结果集合

   return result;

}

说明:该方法在事件发生后,返回需要被通知的Watcher集合。在该方法中,首先会根据EventType类型确定相应的事件类型,然后根据事件类型的不同做出相应的操作:

如针对None类型,即无任何事件,则首先会从三个键值对中删除clientPath对应的Watcher,然后将剩余的Watcher集合添加至结果集合;

针对NodeDataChanged和NodeCreated事件而言,其会从dataWatches和existWatches中删除clientPath对应的Watcher,然后将剩余的Watcher集合添加至结果集合。

八、总结

  针对Watcher机制的第一部分的源码分析就已经完成,本章节需重点关注:

  • 事件的变化,状态的定义依赖于Event内部类的两组枚举值
  • 上下游调用关系图需记忆一下,为加强记忆,再最后再贴一下

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
29天前
|
监控 NoSQL Java
分布式锁实现原理问题之ZooKeeper的观察器(Watcher)特点问题如何解决
分布式锁实现原理问题之ZooKeeper的观察器(Watcher)特点问题如何解决
|
26天前
|
存储 负载均衡 数据库
探索微服务架构中的服务发现机制
【7月更文挑战第24天】在微服务架构的复杂网络中,服务发现是确保通信流畅与系统弹性的关键组件。本文将深入探讨服务发现的工作原理、面临的挑战以及解决方案,同时比较不同服务发现工具的性能特点,旨在为开发者提供实现高效服务发现的实战指南。
|
26天前
|
敏捷开发 设计模式 负载均衡
深入理解微服务架构中的服务发现与注册机制
【7月更文挑战第24天】在微服务架构的海洋中,服务发现与注册机制如同灯塔指引着航行的船只。本文将探索这一机制的重要性、实现原理以及面临的挑战,带领读者领略微服务架构中的关键导航系统。
|
22天前
|
存储 数据库
zookeeper 集群环境搭建及集群选举及数据同步机制
zookeeper 集群环境搭建及集群选举及数据同步机制
30 2
|
1月前
|
存储 负载均衡 开发者
深入理解微服务架构中的服务发现机制
【7月更文挑战第19天】在微服务架构的海洋中,服务发现是一艘至关重要的航船,它指引着各个微服务之间的通信与协作。本文将揭开服务发现的神秘面纱,探索其工作原理、实现方式及面临的挑战,为开发者提供清晰的导航,确保服务间的顺畅航行。
|
30天前
|
API
【想进大厂还不会阅读源码】ShenYu源码-替换ZooKeeper客户端
ShenYu源码阅读。相信大家碰到源码时经常无从下手,不知道从哪开始阅读😭。我认为有一种办法可以解决大家的困扰!至此,我们发现自己开始从大量堆砌的源码中脱离开来😀。ShenYu是一个异步的,高性能的,跨语言的,响应式的 API 网关。
|
30天前
|
敏捷开发 设计模式 监控
探索微服务架构中的服务发现机制
【7月更文挑战第20天】在微服务架构的海洋中,服务发现是一艘必不可少的航船,它指引着各个服务如何相互寻觅和沟通。本文将深入探讨服务发现的核心原理、主流解决方案以及在实际应用中的考量因素,为构建高效、稳定的微服务系统提供导航。
26 2
|
1月前
|
算法 前端开发
|
1月前
|
消息中间件 API 数据库
在微服务架构中,每个服务通常都是一个独立运行、独立部署、独立扩展的组件,它们之间通过轻量级的通信机制(如HTTP/RESTful API、gRPC等)进行通信。
在微服务架构中,每个服务通常都是一个独立运行、独立部署、独立扩展的组件,它们之间通过轻量级的通信机制(如HTTP/RESTful API、gRPC等)进行通信。
|
1月前
|
存储 负载均衡 网络协议
微服务之服务发现机制
微服务的服务发现机制是一种在微服务架构中动态定位服务实例以进行通信的方法。
20 2

相关产品

  • 微服务引擎