Watcher机制(二)WatchManager

简介: 本文深入分析ZooKeeper中WatchManager类的源码,重点解析其如何通过watchTable和watch2Paths两个映射管理Watcher与节点路径的关联关系,涵盖addWatch、removeWatcher、triggerWatch等核心方法的同步机制与执行流程,揭示事件监听与触发的底层原理。

一、前言  前面已经分析了Watcher机制中的第一部分,即在org.apache.zookeeper下的相关类,接着来分析org.apache.zookeeper.server下的WatchManager类。二、WatchManager源码分析2.1 类的属性 

说明:WatcherManager类用于管理watchers和相应的触发器。watchTable表示从节点路径到watcher集合的映射,而watch2Paths则表示从watcher到所有节点路径集合的映射。2.2 核心方法分析1. size方法说明:可以看到size方法是同步的,因此在多线程环境下是安全的,其主要作用是获取watchTable的大小,即遍历watchTable的值集合。2. addWatch方法说明:addWatch方法同样是同步的,其大致流程如下  ① 通过传入的path(节点路径)从watchTable获取相应的watcher集合,进入②  ② 判断①中的watcher是否为空,若为空,则进入③,否则,进入④  ③ 新生成watcher集合,并将路径path和此集合添加至watchTable中,进入④【类似缓存操作】  ④ 将传入的watcher添加至watcher集合,即完成了path和watcher添加至watchTable的步骤,进入⑤  ⑤ 通过传入的watcher从watch2Paths中获取相应的path集合,进入⑥   ⑥ 判断path集合是否为空,若为空,则进入⑦,否则,进入⑧  ⑦ 新生成path集合,并将watcher和paths添加至watch2Paths中,进入⑧  ⑧ 将传入的path(节点路径)添加至path集合,即完成了path和watcher添加至watch2Paths的步骤。综上:addWatche方法会将:1.入参所对应的watcher添加到入参path所对应的全部Watcher集合中,如path下已有则添加,没有创建新的并添加进去;2.入参所对应的path添加到入参watcher所对应给的所有路径集合中,如watcher对应路径为空则创建新的集合进行添加,非空将入参path直接添加进去。3. removeWatcher方法  说明:removeWatcher用作从watch2Paths和watchTable中中移除该watcher,其大致步骤如下  ① 从watch2Paths中移除传入的watcher,并且返回该watcher对应的路径集合,进入②  ② 判断返回的路径集合是否为空,若为空,直接返回,否则,进入③  ③ 遍历②中的路径集合,对每个路径,都从watchTable中取出与该路径对应的watcher集合,进入④  ④ 若③中的watcher集合不为空,则从该集合中移除watcher,并判断移除元素后的集合大小是否为0,若为0,进入⑤  ⑤ 从watchTable中移除路径4. triggerWatch方法 说明:该方法主要用于触发watch事件,并对事件进行处理。其大致步骤如下  ① 根据事件类型、连接状态、节点路径创建WatchedEvent,进入②  ② 从watchTable中移除传入的path对应的键值对,并且返回path对应的watcher集合,进入③  ③ 判断watcher集合是否为空,若为空,则之后会返回null,否则,进入④  ④ 遍历②中的watcher集合,对每个watcher,从watch2Paths中取出path集合,进入⑤  ⑤ 判断④中的path集合是否为空,若不为空,则从集合中移除传入的path。进入⑥  ⑥ 再次遍历watcher集合,对每个watcher,若supress不为空并且包含了该watcher,则跳过,否则,进入⑦  ⑦ 调用watcher的process方法进行相应处理,之后返回watcher集合。【这里的process具体怎么执行的呢】5. dumpWatches方法

Java

运行代码复制代码public synchronized void removeWatcher(Watcher watcher) {

   // 从wach2Paths中移除watcher,并返回watcher对应的path集合

   HashSet<String> paths = watch2Paths.remove(watcher);

   if (paths == null) { // 集合为空,直接返回

       return;

   }

   for (String p : paths) { // 遍历路径集合

       // 从watcher表中根据路径取出相应的watcher集合

       HashSet<Watcher> list = watchTable.get(p);

       if (list != null) { // 若集合不为空

           // 从list中移除该watcher

           list.remove(watcher);

           if (list.size() == 0) { // 移除后list为空,则从watch表中移出

               watchTable.remove(p);

           }

       }

   }

}

public synchronized void dumpWatches(PrintWriter pwriter, boolean byPath) {

if (byPath) { // 控制写入watchTable或watch2Paths

for (Entry<String, HashSet<Watcher>> e : watchTable.entrySet()) { // 遍历每个键值对

// 写入键

pwriter.println(e.getKey());

for (Watcher w : e.getValue()) { // 遍历值(HashSet<Watcher>)

pwriter.print("\t0x");

pwriter.print(Long.toHexString(((ServerCnxn)w).getSessionId()));

pwriter.print("\n");

}

}

} else {

for (Entry<Watcher, HashSet<String>> e : watch2Paths.entrySet()) { // 遍历每个键值对

// 写入"0x"

pwriter.print("0x");

pwriter.println(Long.toHexString(((ServerCnxn)e.getKey()).getSessionId()));

for (String path : e.getValue()) { // 遍历值(HashSet<String>)

//

pwriter.print("\t");

pwriter.println(path);

}

}

}

}

  说明:dumpWatches用作将watchTable或watch2Paths写入磁盘。三、总结  WatchManager类用作管理watcher、其对应的路径以及触发器,其方法都是针对两个映射的操作。


相关文章
|
12天前
|
数据采集 人工智能 安全
|
7天前
|
机器学习/深度学习 人工智能 前端开发
构建AI智能体:七十、小树成林,聚沙成塔:随机森林与大模型的协同进化
随机森林是一种基于决策树的集成学习算法,通过构建多棵决策树并结合它们的预测结果来提高准确性和稳定性。其核心思想包括两个随机性:Bootstrap采样(每棵树使用不同的训练子集)和特征随机选择(每棵树分裂时只考虑部分特征)。这种方法能有效处理大规模高维数据,避免过拟合,并评估特征重要性。随机森林的超参数如树的数量、最大深度等可通过网格搜索优化。该算法兼具强大预测能力和工程化优势,是机器学习中的常用基础模型。
344 164
|
6天前
|
机器学习/深度学习 自然语言处理 机器人
阿里云百炼大模型赋能|打造企业级电话智能体与智能呼叫中心完整方案
畅信达基于阿里云百炼大模型推出MVB2000V5智能呼叫中心方案,融合LLM与MRCP+WebSocket技术,实现语音识别率超95%、低延迟交互。通过电话智能体与座席助手协同,自动化处理80%咨询,降本增效显著,适配金融、电商、医疗等多行业场景。
345 155
|
7天前
|
编解码 人工智能 自然语言处理
⚽阿里云百炼通义万相 2.6 视频生成玩法手册
通义万相Wan 2.6是全球首个支持角色扮演的AI视频生成模型,可基于参考视频形象与音色生成多角色合拍、多镜头叙事的15秒长视频,实现声画同步、智能分镜,适用于影视创作、营销展示等场景。
579 4
|
15天前
|
SQL 自然语言处理 调度
Agent Skills 的一次工程实践
**本文采用 Agent Skills 实现整体智能体**,开发框架采用 AgentScope,模型使用 **qwen3-max**。Agent Skills 是 Anthropic 新推出的一种有别于mcp server的一种开发方式,用于为 AI **引入可共享的专业技能**。经验封装到**可发现、可复用的能力单元**中,每个技能以文件夹形式存在,包含特定任务的指导性说明(SKILL.md 文件)、脚本代码和资源等 。大模型可以根据需要动态加载这些技能,从而扩展自身的功能。目前不少国内外的一些框架也开始支持此种的开发方式,详细介绍如下。
1018 7