11.0 Zookeeper watcher 事件机制原理剖析

news2024/9/22 1:38:18

zookeeper 的 watcher 机制,可以分为四个过程:

  • 客户端注册 watcher。
  • 服务端处理 watcher。
  • 服务端触发 watcher 事件。
  • 客户端回调 watcher。

其中客户端注册 watcher 有三种方式,调用客户端 API 可以分别通过 getData、exists、getChildren 实现,利用前面章节创建的 maven 工程,新建 WatcherDemo 类,以 exists 方法举例说明其原理。

// 导入 ZooKeeper 相关的类
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.data.Stat;

// 定义 WatcherDemo 类,实现 Watcher 接口
public class WatcherDemo implements Watcher {

  // 静态 ZooKeeper 客户端
  static ZooKeeper zooKeeper;

  // 静态代码块,初始化 ZooKeeper 客户端
  static {
    try {
      // 创建 ZooKeeper 客户端实例,连接到 ZooKeeper 服务器
      zooKeeper = new ZooKeeper("192.168.3.39:2181", 4000, new WatcherDemo());
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  // 重写 Watcher 接口的 process 方法,处理 ZooKeeper 事件
  @Override
  public void process(WatchedEvent event) {
    // 打印事件类型
    System.out.println("eventType:" + event.getType());

    // 判断事件类型
    if (event.getType() == Event.EventType.NodeDataChanged) {
      // 节点数据改变事件
      try {
        // 重新注册对节点的监视
        zooKeeper.exists(event.getPath(), true);
      } catch (KeeperException e) {
        e.printStackTrace();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

  // main 方法,程序入口
  public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
    // 定义节点路径
    String path = "/watcher";

    // 判断节点是否存在
    if (zooKeeper.exists(path, false) == null) {
      // 创建节点,并设置初始数据
      zooKeeper.create(path, "0".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
    }

    // 睡眠 1 秒
    Thread.sleep(1000);

    // 打印分割线
    System.out.println("-----------");

    // 重新注册对节点的监视,并设置 Watcher
    Stat stat = zooKeeper.exists(path, true);

    // 等待用户输入
    System.in.read();
  }
}

运行完程序,控制台显示:

此时启动 zookeeper 命令行终端,查看并且删除 watcher 节点:

IDE 控制台输出,触发了节点删除事件:

客户端发送请求给服务端是通过 TCP 长连接建立网络通道,底层默认是通过 java 的 NIO 方式,也可以配置 netty 实现方式。

注册 watcher 监听事件流程图:

1、客户端发送事件通知请求

在 Zookeeper 类调用 exists 方法时候,把创建事件监听封装到 request 对象中,watch 属性设置为 true,待服务端返回 response 后把监听事件封装到客户端的 ZKWatchManager 类中。

2、服务端处理 watcher 事件的请求

服务端 NIOServerCnxn 类用来处理客户端发送过来的请求,最终调用到 FinalRequestProcessor,其中有一段源码添加客户端发送过来的 watcher 事件:

然后进入 statNode 方法,在 DataTree 类方法中添加 watcher 事件,并保存至 WatchManager 的 watchTable 与 watchTable 中。

3、服务端触发 watcher 事件流程:

若服务端某个被监听的节点发生事务请求,服务端处理请求过程中调用 FinalRequestProcessor 类 processRequest 方法中的代码如下所示:

删除调用链最终到 DataTree 类中删除节点分支的触发代码段:

进入 WatchManager 类的 triggerWatch 方法:

继续跟踪进入 NIOServerCnxn,构建了一个 xid 为 -1,zxid 为 -1 的 ReplyHeader 对象,然后再调用 sendResonpe 方法。

4、客户端回调 watcher 事件

客户端 SendThread 类 readResponse 方法接收服务端触发的事件通知,进入 xid 为 -1 流程,处理 Event 事件。

希望你也学会了,更多编程源码模板请来二当家的素材网:https://www.erdangjiade.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1436991.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3 使用defineAsyncComponent 动态加载组件

问题场景 在项目中使用静态加载组件基本能覆盖80%的场景了,如下图 但是我们在需要 循环生成一些的component 的时候或者在 开发ssr服务端渲染的页面 就会遇到有些组件以静态方式导入就会报错,导致进程失败,那么这时候就需要用到动态组件。那…

智能运维适合哪些行业?智能运维需要哪些设备?

构建一个智能运维系统所必须的设备和工具包括: 硬件设备: 服务器:用于部署智能运维平台和存储数据。 网络设备:包括路由器、交换机等,用于连接各种设备和系统。 存储设备:如硬盘、SSD等&am…

时序预测 | Matlab实现基于LSTM长短期记忆神经网络的电力负荷预测模型

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 时序预测 | Matlab实现基于LSTM长短期记忆神经网络的电力负荷预测模型 LSTM(长短期记忆)是一种递归神经网络(RNN)的变体,它在序列数据建模方面表现出色。电力负荷预测是一项重要的任务,可以利用LSTM神经网络…

Adb显示第3方应用的包名原理

Android早期版本实现原理请看 Android源码分析-pm命令的实现,列出包名pm list package,列出系统库pm list libraries_pm list packages-CSDN博客 Android12 对adb shell pm 实现原理做了重构:改成了template模式PackageManagerShellCommand …

如何在 Java 中通过 Map.Entry 访问 Map 的元素

我们使用 Map.Entry 来遍历 ConcurrentHashMap 的代码片段如下&#xff1a; for (Map.Entry<String, String> entry : map.entrySet()) { System.out.println("Key: " entry.getKey() ", Value: " entry.getValue()); } 在 Map.java 中&…

Java20:新特性

一&#xff1a;Lambda表达式&#xff1a; 1. Lambda表达式使用前后对比&#xff1a; 举类一&#xff1a; Testpublic void test(){ Runnable r1 new Runnable() {Overridepublic void run() {System.out.println("我爱北京天安门&#xff01;");} };r1.run();Syst…

华为机考入门python3--(11)牛客11-数字颠倒

分类&#xff1a;字符串 知识点&#xff1a; int转字符串 str int(num) 对字符串进行逆序 my_str str[::-1] 题目来自【牛客】 def reverse_integer(n): # 将整数转换为字符串 str_n str(n) # 使用[::-1]来反转字符串 reversed_str str_n[::-1] return reversed…

FINN: 使用神经网络对网络流进行指纹识别

文章信息 论文题目&#xff1a;FINN: Fingerprinting Network Flows using Neural Networks 期刊&#xff08;会议&#xff09;&#xff1a;Annual Computer Security Applications Conference 时间&#xff1a;2021 级别&#xff1a;CCF B 文章链接&#xff1a;https://dl.ac…

BioTech - 小分子药物设计与优化 概述

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/135998902 小分子药物设计与优化&#xff0c;是利用计算机辅助技术&#xff0c;根据特定的生物学靶点&#xff0c;发现和改进具有治疗作用的小分子…

Codeforces Round 920 (Div. 3)(A~F)

文章目录 ABCDEF A 按题意模拟即可 #include <bits/stdc.h> #define int long long #define rep(i,a,b) for(int i (a); i < (b); i) #define fep(i,a,b) for(int i (a); i > (b); --i) #define pii pair<int, int> #define pll pair<long long, long…

JavaEE作业-实验二

目录 1 实验内容 2 实验要求 3 思路 4 核心代码 5 实验结果 1 实验内容 实现两个整数求和的WEB程序 2 实验要求 ①采用SpringMVC框架实现 ②数据传送到WEB界面采用JSON方式 3 思路 ①创建一个SpringMVC项目&#xff0c;配置好相关的依赖和配置文件。 ②创建一个Con…

Win32 SDK Gui编程系列之--ListView自绘OwnerDraw

ListView自绘OwnerDraw 1.ListView自绘OwnerDraw 正在试错是否使用了列表视图,尽量制作出智能的表格编辑器。本页显示了业主抽签的表格数据(二维数组数据)的显示方法。 显示画面和整个程序如下所示。使用ListView_GetSubItemRect宏的话,就不需要getRect函数了。 当nCol的…

thinkphp获取用户最新的阅读记录,按书籍id去重,返回最新的阅读记录

通过uid查询data_user_zhangjie的记录 去重shuji_id 获取createtime最新的一条数据 //获取用户章节记录public function getUserZhangjieList(){$uid = input(uid);if(empty

Maven构建OSGI+HttpServer应用

Maven构建OSGIHttpServer应用 官网&#xff08;https://eclipse.dev/equinox/server/http_in_equinox.php&#xff09;介绍有两种方式&#xff1a; 一种是基于”org.eclipse.equinox.http”包的轻量级实现&#xff0c;另一种是基于”org.eclipse.equinox.http.jetty”包&#…

jvm体系结构

一、Jvm 的介绍 1、JVM体系结构 2、JVM运行时数据区 3、JVM内存模型 JVM运行时内存 共享内存区 线程内存区 3.1、共享内存区 共享内存区 持久带(方法区 其他) 堆(Old Space Young Space(den S0 S1)) 持久代&#xff1a; JVM用持久带&#xff08;Permanent Space&…

MySQL数据库语句总结

一. 数据定义语言 DDL 数据定义语言&#xff0c;用来定义数据库对象的&#xff08;比如&#xff1a;数据库、表、字段等&#xff09; 1. 数据库操作 &#xff08;1&#xff09;查询所有的数据库 —— show databases; &#xff08;2&#xff09;创建数据库 —— create dat…

【数据结构】二叉树的顺序结构及实现(堆)

1.二叉树的顺序结构 普通的二叉树是不适合用数组来存储的&#xff0c;因为可能会存在大量的空间浪费。而完全二叉树更适合使用顺序结 构存储。现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储&#xff0c;需要注意的是这里的堆和操作系统 虚拟进程地址空间中的堆是两…

架设游戏服务器租用价格?腾讯云和阿里云价格对比

游戏服务器租用多少钱一年&#xff1f;1个月游戏服务器费用多少&#xff1f;阿里云游戏服务器26元1个月、腾讯云游戏服务器32元&#xff0c;游戏服务器配置从4核16G、4核32G、8核32G、16核64G等配置可选&#xff0c;可以选择轻量应用服务器和云服务器&#xff0c;阿腾云atengyu…

蓝桥杯嵌入式学习记录——LCD的使用

目录 一、前言 二、LCD代码的移植 三、LCD代码的调用 一、前言 前一篇文章已经简单记录了一下cubeMX软件的使用和LED的点亮&#xff0c;今天来记录一下LCD的使用。LCD的驱动代码有很多&#xff0c;但实际上在蓝桥杯的比赛中用起来非常简单&#xff0c;因为赛点会提供LCD的驱…

nginx upstream server主动健康检测模块ngx_http_upstream_check_module 使用和源码分析(中)

目录 6. 源码分析6.1 解析指令分析6.2 待检查的服务器的添加和状态查询6.3 本模块的进程初始化函数6.4 准备执行健康检测任务6.5 执行健康检测任务本篇对ngx_http_upstream_check_module的源码实现进行详细分析。 关于配置和使用部分可以查看上篇:nginx upstream server主动健…