6.Watcher机制(三)之ZooKeeper

简介: 本文深入分析ZooKeeper类源码,涵盖其内部类结构、核心属性与构造函数,重点解析create、delete、exists等同步/异步操作的实现机制,揭示Watcher注册管理及请求提交流程,全面展现客户端与服务端交互原理。

一、前言
  前面已经分析了Watcher机制中的大多数类,本篇对于ZKWatchManager的外部类Zookeeper进行分析。
二、ZooKeeper源码分析
2.1 类的内部类
  ZooKeeper的内部类框架图如下图所示
  
  
说明:
ZKWatchManager,Zookeeper的Watcher管理者,其源码在之前已经分析过,不再累赘。
WatchRegistration,抽象类,用作watch注册。
ExistsWatchRegistration,存在性watch注册。
DataWatchRegistration,数据watch注册。
ChildWatchRegistration,子节点注册。
States,枚举类型,表示服务器的状态。

  1. WatchRegistration
      接口类型,表示对路径注册监听。  
    说明:可以看到WatchRegistration包含了Watcher和clientPath字段,表示监听和对应的路径,值得注意的是getWatches方式抽象方法,需要子类实现,而在register方法中会调用getWatches方法,实际上调用的是子类的getWatches方法,这是典型的工厂模式。register方法首先会判定是否需要添加监听,然后再进行相应的操作,在WatchRegistration类的默认实现中shouldAddWatch是判定返回码是否为0。
  2. ExistsWatchRegistration 
    说明:ExistsWatchRegistration 表示对存在性监听的注册,其实现了getWatches方法,并且重写了shouldAddWatch方法,getWatches方法是根据返回码的值确定返回dataWatches或者是existWatches。
  3. DataWatchRegistration
    说明:DataWatchRegistration表示对数据监听的注册,其实现了getWatches方法,返回dataWatches。
  4. ChildWatchRegistration
    说明:ChildWatchRegistration表示对子节点监听的注册,其实现了getWatches方法,返回childWatches。
  5. States
    说明:States为枚举类,表示服务器的状态,其有两个方法,判断服务器是否存活和判断客户端是否连接至服务端。
    2.2 类的属性  
      说明:ZooKeeper类存维护一个ClientCnxn类,用来管理客户端与服务端的连接。  
    2.3 类的构造函数
  6. ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, boolean canBeReadOnly)型构造函数    
      说明:该构造函数会初始化WatchManager的defaultWatcher,同时会解析服务端地址和端口号,之后根据服务端的地址生成HostProvider(其会打乱服务器的地址),之后生成客户端管理并启动,注意此时会调用getClientCnxnSocket函数,其源码如下  
    说明:该函数会利用反射创建ClientCnxnSocketNIO实例
  7. public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, long sessionId, byte[] sessionPasswd, boolean canBeReadOnly) throws IOException型构造函数  
      说明:此型构造函数和之前构造函数的区别在于本构造函数提供了sessionId和sessionPwd,这表明用户已经之前已经连接过服务端,所以能够获取到sessionId,其流程与之前的构造函数类似,不再累赘。
    2.4 核心函数分析
  8. create函数  
    函数签名:
    public String create(final String path, byte data[], List acl, CreateMode createMode)
    throws KeeperException, InterruptedException
    说明:该create函数是同步的,主要用作创建节点,其大致步骤如下
      ① 验证路径是否合法,若不合法,抛出异常,否则进入②
      ② 添加根空间,生成请求头、请求、响应等,并设置相应字段,进入③
      ③ 通过客户端提交请求,判断返回码是否为0,若不是,则抛出异常,否则,进入④
      ④ 除去根空间后,返回响应的路径
      其中会调用submitRequest方法,其源码如下  
    说明:submitRequest会将请求封装成Packet包,然后一直等待packet包响应结束,然后返回;若没结束,则等待。可以看到其是一个同步方法。
  9. create函数
    函数签名:
    public void create(final String path, byte data[], List acl, CreateMode createMode, StringCallback cb, Object ctx)  
    说明:该create函数是异步的,其大致步骤与同步版的create函数相同,只是最后其会将请求打包成packet,然后放入队列等待提交。
  10. delete函数  
    函数签名:public void delete(final String path, int version) throws InterruptedException, KeeperException
    说明:该函数是同步的,其流程与create流程相似,不再累赘。
  11. delete函数
    函数签名:public void delete(final String path, int version, VoidCallback cb, Object ctx)
      说明:该函数是异步的,其流程也相对简单,不再累赘。
  12. multi函数  
    说明:该函数用于执行多个操作或者不执行,其首先会验证每个操作的合法性,然后将每个操作添加根空间后加入到事务列表中,之后会调用multiInternal函数,其源码如下  
    说明:multiInternal函数会提交多个操作并且等待响应结果集,然后判断结果集中是否有异常,若有异常则抛出异常,否则返回响应结果集。
  13. exists函数  
    函数签名:public Stat exists(final String path, Watcher watcher) throws KeeperException, InterruptedException
    Java
    运行代码
    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    public Stat exists(final String path, Watcher watcher)

     throws KeeperException, InterruptedException
    

    {

     final String clientPath = path;
    
     // 验证路径是否合法
     PathUtils.validatePath(clientPath);
     // the watch contains the un-chroot path
     WatchRegistration wcb = null;
     if (watcher != null) { // 生成存在性注册
         wcb = new ExistsWatchRegistration(watcher, clientPath);
     }
     // 添加根空间
     final String serverPath = prependChroot(clientPath);
     // 新生请求头
     RequestHeader h = new RequestHeader();
     // 设置请求头类型
     h.setType(ZooDefs.OpCode.exists);
     // 新生节点存在请求
     ExistsRequest request = new ExistsRequest();
     // 设置路径
     request.setPath(serverPath);
     // 设置Watcher
     request.setWatch(watcher != null);
     // 新生设置数据响应
     SetDataResponse response = new SetDataResponse();
     // 提交请求
     ReplyHeader r = cnxn.submitRequest(h, request, response, wcb);
     if (r.getErr() != 0) { // 判断返回码
         if (r.getErr() == KeeperException.Code.NONODE.intValue()) {
             return null;
         }
         throw KeeperException.create(KeeperException.Code.get(r.getErr()),
                 clientPath);
     }
    
     // 返回结果的状态
     return response.getStat().getCzxid() == -1 ? null : response.getStat();
    

    }
    说明:该函数是同步的,用于判断指定路径的节点是否存在,值得注意的是,其会对指定路径的结点进行注册监听。

  14. exists
    函数签名:public void exists(final String path, Watcher watcher, StatCallback cb, Object ctx) 
    Java
    运行代码
    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    public void exists(final String path, Watcher watcher,
         StatCallback cb, Object ctx)
    
    {
    final String clientPath = path;
    // 验证路径是否合法
    PathUtils.validatePath(clientPath);
    // the watch contains the un-chroot path
    WatchRegistration wcb = null;
    if (watcher != null) { // 生成存在性注册
     wcb = new ExistsWatchRegistration(watcher, clientPath);
    
    }
    // 添加根空间
    final String serverPath = prependChroot(clientPath);
    // 新生请求头
    RequestHeader h = new RequestHeader();
    // 设置请求头类型
    h.setType(ZooDefs.OpCode.exists);
    // 新生节点存在请求
    ExistsRequest request = new ExistsRequest();
    // 设置路径
    request.setPath(serverPath);
    // 设置Watcher
    request.setWatch(watcher != null);
    // 新生设置数据响应
    SetDataResponse response = new SetDataResponse();
    // 将请求封装成packet,放入队列,等待执行
    cnxn.queuePacket(h, new ReplyHeader(), request, response, cb,
                  clientPath, serverPath, ctx, wcb);
    
    }
    说明:该函数是异步的,与同步的流程相似,不再累赘。
    之后的getData、setData、getACL、setACL、getChildren函数均类似,只是生成的响应类别和监听类别不相同,大同小异,不再累赘。
    三、总结
      本篇博文分析了Watcher机制的ZooKeeper类,该类包括了对服务器的很多事务性操作,并且包含了同步和异步两个版本,但是相对来说,较为简单。
相关文章
|
存储 安全 API
【嵌入式系统】DMA工作原理与常用函数解析
【嵌入式系统】DMA工作原理与常用函数解析
1913 0
【嵌入式系统】DMA工作原理与常用函数解析
|
6月前
|
安全
《提前设断点,再也不慌!QClaw长任务防中断指南》
本文直击智能工具长任务中断后进度清零、盲目续传导致内容混乱的普遍痛点,剖析了“直接说接着写”这种原始方式成功率极低的底层原因。文章指出QClaw断点续传的本质是手动重建任务状态快照,而非简单复制全文,系统讲解了提取逻辑骨架、补充原始约束、增量分块续传、预先设置天然断点、跨会话状态持久化等核心实操技巧。同时点明断点续传不仅是工具功能,更是一种长任务管理思维,能帮助使用者彻底摆脱进度丢失的困扰,大幅提升复杂长任务的处理效率。
390 8
|
12月前
|
监控 算法 图形学
《2D角色+3D场景:动漫游戏次元融合的技术突破路径》
本文围绕古风仙侠动漫游戏开发,聚焦2D手绘角色与3D场景的融合难题,针对图层割裂、阴影脱节、透视失真、光照不匹配、多角色性能压力及互动割裂六大问题,分别提出骨骼绑定控制器、动态阴影投射、非线性透视缩放、实时调色、分层渲染、互动姿态匹配六大解决方案。通过差异化参数设置与动态精度调整,在保证动漫风格的同时,解决技术痛点,提升场景沉浸感。
951 3
|
6月前
|
人工智能 自然语言处理 监控
阿里云JVS Claw是什么?JVS Claw“养虾”功能与优势,免费体验版和最新包年包月优惠
阿里云JVS Claw是“云上养虾神器”,可简化大模型使用流程,支持零门槛创建、管理和优化AI智能体。其核心功能包括一键接入OpenClaw、多端协同操作、提供安全隔离环境及自进化技能体系,满足企业及个人智能化需求。新用户可享7天免费体验,首月39元起,且提供包月包年优惠。此外,用户也可选用轻量云服务器部署OpenClaw,有多个规格的云服务器可供选择。
|
6月前
|
数据采集
企业知识库上线 Claude 的实战方案:三层架构直接抄作业
企业引入Claude做知识处理,应先构建可治理的知识链路,而非仅替换搜索框。聚焦知识入库质量、答案可追溯、成本可归因、模型可切换四大目标,分三层(资产加工、分级问答、统一接入)稳建系统,兼顾能力与合规。
513 0
|
边缘计算 人工智能 自动驾驶
云计算的加速引擎——5G技术如何改变未来
云计算的加速引擎——5G技术如何改变未来
518 7
云计算的加速引擎——5G技术如何改变未来
|
Kubernetes 监控 Cloud Native
快速部署YuniKorn开启全能管理与调度器
本文介绍了YuniKorn的基本信息,并通过阿里云计算巢完成了YuniKorn的快速部署,使用者不需要自己下载代码,不需要自己安装复杂的依赖,不需要了解底层技术,只需要在控制台图形界面点击几下鼠标就可以快速部署并启动YuniKorn,非技术同学也能轻松搞定。
|
数据安全/隐私保护
基于MATLAB的PEF湍流风场生成器模拟与仿真
本课题基于MATLAB 2022a开发PEF(Primitive Equations Formulation)湍流风场生成器,模拟大气流动和气象现象。PEF模型考虑地球旋转效应、层结稳定性及湍流混合等复杂物理过程,适用于大尺度天气系统研究。核心程序采用高斯分布尾流模型,计算尾流中心到转子中心的距离,并绘制风速分布图。仿真结果展示了不同条件下的风场特征,无水印输出。该模型在天气预报和气候研究中具有重要应用价值。
|
人工智能 自然语言处理 BI
蓝凌aiKM,双能驱动场景变革:蓝凌知识管理平台和通义千问共建实践
蓝凌aiKM通过双能驱动场景变革,结合蓝凌知识管理平台与通义千问大模型,助力企业构建智能“大脑”。aiKM不仅提升知识管理效率,还赋能业务场景,如新人培训、营销支持和流程优化。蓝博士产品整合专属内容与大模型能力,提供智能搜索、问答及推荐服务,帮助企业高效利用私域知识资产,推动数字化转型。蓝凌在AI时代致力于激活企业新生产力,打造知识护城河,成为核心竞争力。
776 0
|
IDE Linux 开发工具
Linux 创建 intellij-idea快捷方式
Linux 创建 intellij-idea快捷方式
981 0