背景

项目中使用了zookeeper进行的类似工作流引擎的工作流转,将一次工作请求拆分了4个节点(S/E/T/L)。S阶段做完后,通过zk的watcher触发下一个E节点进行处理,S和E可能为不同的jvm上,所以需要走一个分布式的消息进行通知。

思路

基于zookeeper做持久化watcher,项目中直接使用zookeeper官方api,大致的工作模型:

1.private synchronized void initNodes(List<String> nodes) {
2.    // 根据zk节点,判断是否需要处理
3.}
4.
5.private void syncNodes() {
6.        try {
7.            List<String> nodes = zookeeper.getChildren(ArbitrateConstants.NODE_NID_ROOT, new AsyncWatcher() {
8.
9.                public void asyncProcess(WatchedEvent event) {
10.                    syncNodes();// 继续关注node节点变化
11.                }
12.            });
13.
14.            initNodes(nodes);
15.        } catch (KeeperException e) {
16.            syncNodes();
17.        } catch (InterruptedException e) {
18.            // ignore
19.        }
20.    }
  • 有两个方法initNodes 和 syncNodes,  syncNodes主要是监听zookeeper的节点变化
  • syncNodes会通过级联方式,在每次watcher被触发后,就会再挂一次watcher。完成了一个类似链式触发的功能

遇到的问题

系统上线运行后,跑了几天时间,跑出了一个OutOfMemory的问题,jmap dump了下对应的内存数据文件,发现了一个zk使用上的问题.

a. 通过mat分析查看了下jvm中占用内存最大的对象,居然是zookeeper中的一个waitingEvents.:

b. waitingEvents中的WatcherSetEventPair对象中,包含了一个待响应的watchers和对应的响应event事件对象,对应的watchers数量居然有300W个

问题分析:

分析了下WatcherSetEventPair中的处理机制。

Event响应中对应EventType的枚举类型:(存在一个特殊的None类型)

  • None (-1),
  • NodeCreated (1),
  • NodeDeleted (2),
  • NodeDataChanged (3),
  • NodeChildrenChanged (4);
查了下代码,None类型会在Session expired / connection loss/  auth failed得到对应的触发,对应的触发path为null
代码:
1.eventThread.queueEvent(new WatchedEvent(
2.                        Watcher.Event.EventType.None,
3.                        Watcher.Event.KeeperState.Expired, null));

针对None类型,在获取对应的watcher响应时:

1.public Set<Watcher> materialize(Watcher.Event.KeeperState state,
2.                                        Watcher.Event.EventType type,
3.                                        String clientPath)
4.        {
5.            Set<Watcher> result = new HashSet<Watcher>();
6.
7.            switch (type) {
8.            case None:
9.                result.add(defaultWatcher);
10.                for(Set<Watcher> ws: dataWatches.values()) {
11.                    result.addAll(ws);
12.                }
13.                for(Set<Watcher> ws: existWatches.values()) {
14.                    result.addAll(ws);
15.                }
16.                for(Set<Watcher> ws: childWatches.values()) {
17.                    result.addAll(ws);
18.                }
19.
20.                // clear the watches if auto watch reset is not enabled
21.                if (ClientCnxn.getDisableAutoResetWatch() &&
22.                        state != Watcher.Event.KeeperState.SyncConnected)
23.                {
24.                    synchronized(dataWatches) {
25.                        dataWatches.clear();
26.                    }
27.                    synchronized(existWatches) {
28.                        existWatches.clear();
29.                    }
30.                    synchronized(childWatches) {
31.                        childWatches.clear();
32.                    }
33.                }
34.
35.                return result;
针对出现None的类型,会将所有的watcher进行触发,同时并不会移除watcher,所以,watcher会在下一次reconnect成功后再次触发,除非设置DisableAutoResetWatch

总结

a.  需要明确watcher的触发条件和触发case场景。特别注意,None类型可能会引起触发2次watcher调用

(截取了淘宝同学的blog : http://rdc.taobao.com/team/jm/archives/1047)

event For “/path”defaultWatcherexists
(“/path”)
getData
(“/path”)
getChildren
(“/path”)

EventType.None
EventType.NodeCreated    
EventType.NodeDeleted    
EventType.NodeDataChanged    
EventType.NodeChildrenChanged      

b.  出现session expired,需要重建zookeeper connector,对应的watcher会失效。因为watcher在client的存储是和对应的zookeeper client绑定,不同的client有不同的watcher列表。

zookeeper watcher使用注意点相关推荐

  1. zookeeper watch java_Apache ZooKeeper Watcher 机制源码解释

    分布式系统从根本上来说就是不同节点上的进程并发执行,并且相互之间对进程的行为进行协调处理的过程.不同节点上的进程互相协调行为的过程叫做分布式同步.许多分布式系统需要一个进程作为任务的协调者,执行一些其 ...

  2. zookeeper - watcher(9)

    watcher的特征 zookeeper的一大特点之一就是watch机制,所有基于zookeeper的消息通知机制基本上都是建议在watcher机制之上的,比如业界比较有名的由360公司开源的Qcon ...

  3. Zookeeper Watcher(事件监听器)?

    Watcher(事件监听器),是 ZooKeeper 中的一个很重要的特性.ZooKeeper 允许用户在指定节点上注册一些 Watcher,并且在一些特定事件触发的时候,ZooKeeper 服务端会 ...

  4. zookeeper watcher机制

    2019独角兽企业重金招聘Python工程师标准>>> 客户端ClientWatchManager,管理由ClientXncn产生的watchers和handle events.在z ...

  5. Zookeeper——Watcher原理详解

    文章目录 引言 正文 一.如何注册监听 二.如何触发监听事件 三.事件类型有哪些 四.Watcher可以被无限次触发么?为什么要这么设计? 五.Watcher实现原理 1. 客服端发送请求 a. 初始 ...

  6. Zookeeper Watcher 机制

    Zookeeper 允许客户端向服务端的某个 Znode 注册一个 Watcher 监听,当服务 端的一些指定事件触发了这个 Watcher,服务端会向指定客户端发送一个事件通 知来实现分布式的通知功 ...

  7. zookeeper -- 第四章 zookeeper watcher讲解

    2019独角兽企业重金招聘Python工程师标准>>> 先站坑 转载于:https://my.oschina.net/u/3136594/blog/1610091

  8. 【hortonworks/registry】NoClassDefFoundError: org/apache/zookeeper/Watcher

    1.概述 hortonworks/registry 搭建高可用环境,环境配置如下 ## HA configuration ## When no configuration is set, then a ...

  9. Ⅵ:zookeeper的Watcher事件监听机制

    2021最新zookeeper系列 ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤ ...

  10. ZooKeeper入门(三)zookeeper的Watcher机制

    process方法是Watcher接口中的一个回调方法,当ZooKeeper向客户端发送一个Watcher事件通知时,客户端就会对相应的process方法进行回调,从而实现对事件的处理. import ...

最新文章

  1. Blender 和Unreal Engine中的模块化3D建筑技能学习视频教程
  2. 面试官:你分析过mybatis工作原理吗?
  3. 关于串口接收数据不全的问题
  4. Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver 驱动问题处理办法
  5. 动态控制SAP C4C UI元素的显示和隐藏
  6. NOIP2007 树网的核
  7. css线条伸缩_CSS3弹性伸缩布局之box布局
  8. fixedsys字体 win7_主编为你win7系统显示默认隐藏字体的图文办法
  9. Delphi 10.4.2 CE 社区版支持 Android API-30,之二
  10. IDEA+EmmyLua Lua开发环境搭建
  11. coreldraw的线条怎么变成圆头_CDR的一些技巧
  12. IDEA 出现编译错误 Multi-catches are not supported a this language level 解决方法
  13. 灵遁者散文小说集《从今往后》:永远都是开始
  14. 解析12306订票流程
  15. Python数据分析 | (31) 透视表和交叉表
  16. java根据某天获取当前周的日期
  17. python包从一台电脑迁移拷贝到另一台电脑
  18. python数据处理7: matplotlib绘图保存图片深入
  19. 五线谱音名和组别对照表_认识五线谱,大谱表与钢琴对照表
  20. vscode一格式化就报错?各种风格问题各种报错烦不胜烦,教你如何用好vue的eslint风格配置...

热门文章

  1. LNMP 常见问题(FAQ)
  2. 将15位的身份证号码升级到18位的关键是校验码
  3. 学习git: 忽略某些文件(夹)的跟踪
  4. 2014浙大ACM网络省赛-----Talented Chef问题(Problem -C)
  5. 限制UITextView输入字数(兼容iOS7)
  6. SSH Config Editor Mac(SSH配置编辑器)V2.2
  7. 使用Xilisoft iPad Magic Platinum for Mac将任何视频/音频转换和传输到 iPad/iPod/iPhone/iTunes?
  8. Mac 上删除用户或群组教程
  9. 【Flutter】Dart的数据类型listMap(数组和字典)
  10. iOS底层探索之Runtime(五): 消息转发