zookeeper watcher使用注意点
背景
项目中使用了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);
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;
总结
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使用注意点相关推荐
- zookeeper watch java_Apache ZooKeeper Watcher 机制源码解释
分布式系统从根本上来说就是不同节点上的进程并发执行,并且相互之间对进程的行为进行协调处理的过程.不同节点上的进程互相协调行为的过程叫做分布式同步.许多分布式系统需要一个进程作为任务的协调者,执行一些其 ...
- zookeeper - watcher(9)
watcher的特征 zookeeper的一大特点之一就是watch机制,所有基于zookeeper的消息通知机制基本上都是建议在watcher机制之上的,比如业界比较有名的由360公司开源的Qcon ...
- Zookeeper Watcher(事件监听器)?
Watcher(事件监听器),是 ZooKeeper 中的一个很重要的特性.ZooKeeper 允许用户在指定节点上注册一些 Watcher,并且在一些特定事件触发的时候,ZooKeeper 服务端会 ...
- zookeeper watcher机制
2019独角兽企业重金招聘Python工程师标准>>> 客户端ClientWatchManager,管理由ClientXncn产生的watchers和handle events.在z ...
- Zookeeper——Watcher原理详解
文章目录 引言 正文 一.如何注册监听 二.如何触发监听事件 三.事件类型有哪些 四.Watcher可以被无限次触发么?为什么要这么设计? 五.Watcher实现原理 1. 客服端发送请求 a. 初始 ...
- Zookeeper Watcher 机制
Zookeeper 允许客户端向服务端的某个 Znode 注册一个 Watcher 监听,当服务 端的一些指定事件触发了这个 Watcher,服务端会向指定客户端发送一个事件通 知来实现分布式的通知功 ...
- zookeeper -- 第四章 zookeeper watcher讲解
2019独角兽企业重金招聘Python工程师标准>>> 先站坑 转载于:https://my.oschina.net/u/3136594/blog/1610091
- 【hortonworks/registry】NoClassDefFoundError: org/apache/zookeeper/Watcher
1.概述 hortonworks/registry 搭建高可用环境,环境配置如下 ## HA configuration ## When no configuration is set, then a ...
- Ⅵ:zookeeper的Watcher事件监听机制
2021最新zookeeper系列 ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤️ ❤ ...
- ZooKeeper入门(三)zookeeper的Watcher机制
process方法是Watcher接口中的一个回调方法,当ZooKeeper向客户端发送一个Watcher事件通知时,客户端就会对相应的process方法进行回调,从而实现对事件的处理. import ...
最新文章
- Blender 和Unreal Engine中的模块化3D建筑技能学习视频教程
- 面试官:你分析过mybatis工作原理吗?
- 关于串口接收数据不全的问题
- Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver 驱动问题处理办法
- 动态控制SAP C4C UI元素的显示和隐藏
- NOIP2007 树网的核
- css线条伸缩_CSS3弹性伸缩布局之box布局
- fixedsys字体 win7_主编为你win7系统显示默认隐藏字体的图文办法
- Delphi 10.4.2 CE 社区版支持 Android API-30,之二
- IDEA+EmmyLua Lua开发环境搭建
- coreldraw的线条怎么变成圆头_CDR的一些技巧
- IDEA 出现编译错误 Multi-catches are not supported a this language level 解决方法
- 灵遁者散文小说集《从今往后》:永远都是开始
- 解析12306订票流程
- Python数据分析 | (31) 透视表和交叉表
- java根据某天获取当前周的日期
- python包从一台电脑迁移拷贝到另一台电脑
- python数据处理7: matplotlib绘图保存图片深入
- 五线谱音名和组别对照表_认识五线谱,大谱表与钢琴对照表
- vscode一格式化就报错?各种风格问题各种报错烦不胜烦,教你如何用好vue的eslint风格配置...
热门文章
- LNMP 常见问题(FAQ)
- 将15位的身份证号码升级到18位的关键是校验码
- 学习git: 忽略某些文件(夹)的跟踪
- 2014浙大ACM网络省赛-----Talented Chef问题(Problem -C)
- 限制UITextView输入字数(兼容iOS7)
- SSH Config Editor Mac(SSH配置编辑器)V2.2
- 使用Xilisoft iPad Magic Platinum for Mac将任何视频/音频转换和传输到 iPad/iPod/iPhone/iTunes?
- Mac 上删除用户或群组教程
- 【Flutter】Dart的数据类型listMap(数组和字典)
- iOS底层探索之Runtime(五): 消息转发