Zookeeper:事件监听和通知机制

Zookeeper 允许客户端向服务端的某个 Znode 注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据 Watcher 通知状态和事件类型做出业务上的改变。

~

本篇内容包括:关于观察者模式、Zookeeper 事件监听和通知机制、Zookeeper 工作流程


文章目录

    • 一、关于观察者模式
        • 1、观察者模式
        • 2、发布-订阅模式
        • 3、Zookeeper 中的观察者模式
    • 二、Zookeeper 事件监听和通知机制
        • 1、Zookeeper Watcher 机制
        • 2、Watcher 特性
    • 三、Zookeeper 工作流程
        • 1、客户端注册 Watcher
        • 2、服务器处理 Watcher
        • 3、客户端回调 Watcher


一、关于观察者模式

1、观察者模式

观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新。观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯。观察者模式有一个别名叫“发布-订阅模式”,或者说是“订阅-发布模式”,订阅者和订阅目标是联系在一起的,当订阅目标发生改变时,逐个通知订阅者。

  • 作用:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
  • 优点:
    1. 观察者和被观察者是抽象耦合的
    2. 建立一套触发机制
  • 缺点
    1. 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
    2. 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
    3. 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

2、发布-订阅模式

发布-订阅模式并不属于 24 种基本的设计模式,起初只是观察者模式的一个别称,但是经过时间的沉淀,似乎他已经强大了起来,已经独立于观察者模式,成为另外一种不同的设计模式。

现在的发布订阅模式中,称为发布者的消息发送者不会将消息直接发送给订阅者,这意味着发布者和订阅者不知道彼此的存在。在发布者和订阅者之间存在第三个组件,称为消息代理或调度中心或中间件,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息并相应地分发它们给订阅者。

  • 作用:发布-订阅模式是前端常用的一种设计模式,现在主流的 MVVM 框架,都大量使用了此设计模式,其主要作用有以下两点:
    • 可以实现模块间通信
    • 可以在一定程度上实现异步编程
  • 优点:
    • 支持简单的广播通信,当对象状态发生改变时,会自动通知已经订阅过的对象(我们日常工作中也经常使用到,比如我们的 ajax 请求,请求有 successerror 的回调函数,我们可以订阅 ajax 的 successerror 事件。我们并不关心对象在异步运行的状态,我们只关心 success 的时候或者 error 的时候我们要做点我们自己的事情就可以了~)。
    • 发布者与订阅者耦合性降低,发布者只管发布一条消息出去,它不关心这条消息如何被订阅者使用,同时,订阅者只监听发布者的事件名,只要发布者的事件名不变,它不管发布者如何改变
  • 缺点
    • 创建订阅者需要消耗一定的时间和内存。
    • 虽然可以弱化对象之间的联系,如果过度使用的话,反而使代码不好理解及代码不好维护等等。

3、Zookeeper 中的观察者模式

zookeeper 从设计模式上来看,是一个基于观察者模式设计(或者说“发布-订阅模式”更为贴切)的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生了变化,Zookeeper 就将负责通知已经在 Zookeeper 上注册的观察者做出相应的反应,从而实现集群中类似 Master/slave 管理模式。


二、Zookeeper 事件监听和通知机制

1、Zookeeper Watcher 机制

Zookeeper 允许客户端向服务端的某个 Znode 注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据 Watcher 通知状态和事件类型做出业务上的改变。

Watcher 基于 Zookeeper 上创建的 Znode 节点,可以对这些节点绑定监听事件,比如可以监听节点数据变更、节点删除、子节点状态变更等事件,通过这个事件机制,可以基于 Zookeeper 实现分布式锁,发布订阅(多个订阅者同时监听某一个主题对象,当这个主题对象自身状态发生变化时,会通知所有订阅者)等功能。

2、Watcher 特性

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

  • 一次性:watcher 是一次性的,一旦触发就会被移除,再次使用时需要重新注册;
  • 客户端顺序回调:watcher 回调是顺序串行执行的,只有回调后客户端才能看到最新的数据状态,一个 watcher 回调逻辑不应太多。以免影响其他回调 watcher 执行;
  • 轻量级:WatchEvent 是最小的通信单位,结构上只包含通知状态、事件类型和节点路径,并不会告诉姐点变化的前后具体内容;
  • 实效性:watcher 只有在当前 session 彻底失效时才会无效,若在 session 有效期内快速重连成功,则 watcher 依然存在,仍可接收到通知。

三、Zookeeper 工作流程

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

  1. 客户端注册 Watcher 到服务端;

  2. 服务端发生数据变更;

  3. 服务端通知客户端数据变更;

  4. 客户端回调 Watcher 处理变更应对逻辑;

1、客户端注册 Watcher

Zookeeper 中注册 watcher的 接口大概有如下几个:

  1. 建立 Zookeeper 连接时传入的 watcher;
  2. 通过 gtData、exists、getChildren; 来设置watcher,而它们又各有同步和异步两种形式。Zookeeper 的所有读操作都可以设置 watch 监视点: getData, getChildren, exists. 写操作则是不能设置监视点的。

监视有两种类型:数据监视点和子节点监视点。创建、删除或者设置znode都会触发这些监视点。exists,getData 可以设置数据监视点。getChildren 可以设置子节点变化。而可能监测的事件类型有: None、NodeCreated、NodeDataChanged、NodeDeleted、NodeChildrenChanged。

 None // 客户端连接状态发生变化的时候 会收到None事件NodeCreated // 节点创建事件   NodeDeleted // 节点删除事件NodeDataChanged // 节点数据变化NodeChildrenChanged // 子节点被创建 删除触发该事件

# 客户端注册流程:

  1. 调用 getData()/getChildren()/exist()三个 API,传入 Watcher 对象
  2. 标记请求 request,封装 Watcher 到 WatchRegistration
  3. 封装成 Packet 对象,发服务端发送 request
  4. 收到服务端响应后,将 Watcher 注册到 ZKWatcherManager 中进行管理
  5. 请求返回,完成注册。

2、服务器处理 Watcher

# 服务端接收 Watcher 并存储

接收到客户端请求,处理请求判断是否需要注册 Watcher,需要的话将数据节点的节点路径和 ServerCnxn(ServerCnxn 代表一个客户端和服务端的连接,实现了 Watcher 的 process 接口,此时可以看成一个 Watcher 对象)存储在WatcherManager 的 WatchTable 和 watch2Paths 中去。

# Watcher 触发
以服务端接收到 setData() 事务请求触发 NodeDataChanged 事件为例:

  • 封装 WatchedEvent:将通知状态(SyncConnected)、事件类型(NodeDataChanged)以及节点路径封装成一个 WatchedEvent 对象
  • 查询 Watcher:从 WatchTable 中根据节点路径查找 Watcher
  • 没找到:说明没有客户端在该数据节点上注册过 Watcher
  • 找到:提取并从 WatchTable 和 Watch2Paths 中删除对应 Watcher(从这里可以看出 Watcher 在服务端是一次性的,触发一次就失效了)

# 调用 process 方法来触发 Watcher
这里 process 主要就是通过 ServerCnxn 对应的 TCP 连接发送 Watcher 事件通知。

3、客户端回调 Watcher

客户端 SendThread 线程接收事件通知,交由 EventThread 线程回调 Watcher。

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

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

相关文章

Linux namespace之:mount namespace

理解mount namespace 用户通常使用mount命令来挂载普通文件系统,但实际上mount能挂载的东西非常多,甚至连现在功能完善的Linux系统,其内核的正常运行也都依赖于挂载功能,比如挂载根文件系统/。其实所有的挂载功能和挂载信息都由内…

Linux namespace之:network namespace

理解network namespace network namespace用来隔离网络环境,「在network namespace中,网络设备、端口、套接字、网络协议栈、路由表、防火墙规则等都是独立的」。 因network namespace中具有独立的网络协议栈,因此每个network namespace中都…

Kubernetes 的原理

kubernetes 已经成为容器编排领域的王者,它是基于容器的集群编排引擎,具备扩展集群、滚动升级回滚、弹性伸缩、自动治愈、服务发现等多种特性能力。 本文将带着大家快速了解 kubernetes ,了解我们谈论 kubernetes 都是在谈论什么。 kuberne…

Zookeeper:实现“分布式锁”的 Demo

Zookeeper 能保证数据的强一致性,用户任何时候都可以相信集群中每个节点的数据都是相同的。一个用户创建一个节点作为锁,另一个用户检测该节点,如果存在,代表别的用户已经锁住,如果不存在,则可以创建一个节…

JavaIO流:案例

java.io 包下需要掌握的流有 16 个,本篇内容包括:java.io包下需要掌握的流、Java IO 案例。 文章目录一、java.io包下需要掌握的流二、Java IO 案例1、Demo 1(FileInputStream)2、Demo 2(FileInputStream)3…

比对excel数据

#!/usr/bin/env pythonimport openpyxl from openpyxl.styles import PatternFill from openpyxl.styles import colors from openpyxl.styles import Font, Color aD:/测算单位设置/比对/吉林/tmp001.xlsx bD:/测算单位设置/比对/吉林/国网吉林电力.xlsx cD:/测算单位设置/比对…

CPU 是如何执行任务的

前言 你清楚下面这几个问题吗? 有了内存,为什么还需要 CPU Cache? CPU 是怎么读写数据的? 如何让 CPU 能读取数据更快一些? CPU 伪共享是如何发生的?又该如何避免? CPU 是如何调度任务的&a…

Ansible 的自动化运维

1、Ansible 特点 Ansible 自 2012 年发布以来,很快在全球流行,其特点如下: Ansible 基于 Python 开发,运维工程师对其二次开发相对比较容易; Ansible 丰富的内置模块,几乎可以满足一切要求; …

Shell 信号发送与捕捉

1、Linux信号类型 信号(Signal):信号是在软件层次上对中断机制的一种模拟,通过给一个进程发送信号,执行相应的处理函数。 进程可以通过三种方式来响应一个信号: 1)忽略信号,即对信…

运维面试题总结

集群相关 简述 ETCD 及其特点? etcd 是 CoreOS 团队发起的开源项目,是一个管理配置信息和服务发现(service discovery)的项目,它的目标是构建一个高可用的分布式键值(key-value)数据库&#x…

详解设计模式:建造者模式

建造者模式(Builder Pattern)也叫做生成器模式,是 GoF 的 23 种设计模式的一种,它将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 当我们需要实列化一个复杂的类,以得到不同结…

图文并茂 VLAN 详解,让你看一遍就理解 VLAN

一、为什么需要VLAN 1.1、什么是VLAN? VLAN(Virtual LAN),翻译成中文是“虚拟局域网”。LAN可以是由少数几台家用计算机构成的网络,也可以是数以百计的计算机构成的企业网络。VLAN所指的LAN特指使用路由器分割的网络——也就是广播域。 在此让我们先复习…

认识VLAN,并学会VLAN的划分和网络配置实例

VLAN的划分和网络的配置实例 1、VLAN基础知识 VLAN(Virtual Local Area Network)的中文名为:“虚拟局域网”,注意和VPN(虚拟专用网)进行区分。 VLAN是一种将局域网设备从逻辑上划分(不是从物…

VLAN划分及配置注意事项

VLAN(Virtual Local Area Network)即虚拟局域网,是将一个物理的LAN在逻辑上划分成多个广播域的通信技术。VLAN内的主机间可以直接通信,而VLAN间不能直接通信,从而将广播报文限制在一个VLAN内。VLAN之间的通信是通过第3…

Docker原理剖析

一、简介 1、了解Docker的前生LXC LXC为Linux Container的简写。可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。相当于C中的NameSpace。容器有效地将由单个操作系统管理的资源划分到孤立的组中&#…

获取Linux内存、cpu、磁盘IO等信息

#!/bin/bash # 获取要监控的本地服务器IP地址 IPifconfig | grep inet | grep -vE inet6|127.0.0.1 | awk {print $2} echo "IP地址:"$IP# 获取cpu总核数 cpu_numgrep -c "model name" /proc/cpuinfo echo "cpu总核数:"$c…

Docker容器网络解析

Docker 容器网络的发展历史 在 Dokcer 发布之初,Docker 是将网络、管理、安全等集成在一起的,其中网络模块可以为容器提供桥接网络、主机网络等简单的网络功能。 从 1.7 版本开始,Docker正是把网络和存储这两部分的功能都以插件化形式剥离出来…

将指定excel的一列数据提取到另一个excel的指定列

#!/usr/bin/env python import openpyxl bjD:/地市县公司/西藏台账数据分析-设备台帐分析.xlsx wb openpyxl.load_workbook (bj) get_sheets wb.sheetnames #print(get_sheets) TA01TA01 TA02TA02 TA03TA03 TE01TE01 YG201YG201 YG202YG202 YG203YG203 YG204YG204 YG205YG205…

Docker 数据管理介绍

默认容器的数据是保存在容器的可读写层,当容器被删除时其上的数据也会丢失,所以为了实现数据的持久性则需要选择一种数据持久技术来保存数据。官方提供了三种存储方式:Volumes、Bind mounts和tmpfs。前面还介绍了:Docker 服务终端…

Docker 数据持久化的三种方案

容器中的数据可以存储在容器层。但是将数据存放在容器层存在以下问题: 数据不是持久化。意思是如果容器删除了,这些数据也就没了 主机上的其它进程不方便访问这些数据 对这些数据的I/O会经过存储驱动,然后到达主机,引入了一层间…