`
agapple
  • 浏览: 1582778 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

zookeeper watcher使用注意点

阅读更多

背景

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

思路

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

 

private synchronized void initNodes(List<String> nodes) {
    // 根据zk节点,判断是否需要处理
}

private void syncNodes() {
        try {
            List<String> nodes = zookeeper.getChildren(ArbitrateConstants.NODE_NID_ROOT, new AsyncWatcher() {

                public void asyncProcess(WatchedEvent event) {
                    syncNodes();// 继续关注node节点变化
                }
            });

            initNodes(nodes);
        } catch (KeeperException e) {
            syncNodes();
        } catch (InterruptedException e) {
            // ignore
        }
    }

 

  • 有两个方法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
代码:
eventThread.queueEvent(new WatchedEvent(
                        Watcher.Event.EventType.None,
                        Watcher.Event.KeeperState.Expired, null));
针对None类型,在获取对应的watcher响应时:
public Set<Watcher> materialize(Watcher.Event.KeeperState state,
                                        Watcher.Event.EventType type,
                                        String clientPath)
        {
            Set<Watcher> result = new HashSet<Watcher>();

            switch (type) {
            case None:
                result.add(defaultWatcher);
                for(Set<Watcher> ws: dataWatches.values()) {
                    result.addAll(ws);
                }
                for(Set<Watcher> ws: existWatches.values()) {
                    result.addAll(ws);
                }
                for(Set<Watcher> ws: childWatches.values()) {
                    result.addAll(ws);
                }

                // clear the watches if auto watch reset is not enabled
                if (ClientCnxn.getDisableAutoResetWatch() &&
                        state != Watcher.Event.KeeperState.SyncConnected)
                {
                    synchronized(dataWatches) {
                        dataWatches.clear();
                    }
                    synchronized(existWatches) {
                        existWatches.clear();
                    }
                    synchronized(childWatches) {
                        childWatches.clear();
                    }
                }

                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列表。

 

  • 大小: 64.4 KB
  • 大小: 168.6 KB
分享到:
评论
3 楼 agapple 2012-12-03  
hoar 写道
请问一下,watcher在每次触发之后就被清除了,怎么才能保证监控到每次变化哪?在被触发的watcher里再添加一个,在这个空隙阶段的变化,新添加的触发器能知道么?


这段空隙阶段的变化,你只能通过获取当前数据的最新值,自己进行判断。
比如
   List resut = zookeeper.getChindren(path , watcher);
你可以拿到当前最新版本的result,然后和内存中的上一个版本做对比,才可以知道具体变化的值。

而且zookeeper的watcher的设计,也只会告诉你有变化,但不会告诉你具体变化的内容是什么
2 楼 3GQQ2012 2012-11-27  
hoar 写道
请问一下,watcher在每次触发之后就被清除了,怎么才能保证监控到每次变化哪?在被触发的watcher里再添加一个,在这个空隙阶段的变化,新添加的触发器能知道么?

无法知道.zk的是为实现路由设计的,watcher功能是一种补充,不是常规武器。
1 楼 hoar 2012-11-16  
请问一下,watcher在每次触发之后就被清除了,怎么才能保证监控到每次变化哪?在被触发的watcher里再添加一个,在这个空隙阶段的变化,新添加的触发器能知道么?

相关推荐

    zookeeper-watcher- 简单例子

    NULL 博文链接:https://xkorey.iteye.com/blog/2204495

    zookeeper-watcher-demo:动物园管理员 wather 演示

    zookeeper-watcher-demo zookeeper wather demo 示例说明:zookeeper server端,client端每100毫秒写入数据,另一个client端watch节点数据变化 监听的结果是得到的数值是连续的、和数据生成端是一致的,并没有出现...

    zookeeper流程图.vsdx

    zookeeper的watcher机制,服务端和客户端你的源码流程,个人总结,个人复习使用

    Zookeeper学习总结

    如果在创建znode时Flag设置为EPHEMERAL,那么当创建这个znode的节点和Zookeeper失去连接后,这个znode将不再存在在Zookeeper里,Zookeeper使用Watcher察觉事件信息。当客户端接收到事件信息,比如连接超时、节点数据...

    ZooKeeper面试题(2020最新版)

    Zookeeper Watcher 机制 — 数据变更通知7. 客户端注册 Watcher 实现8. 服务端处理 Watcher 实现9. 客户端回调 Watcher10. ACL 权限控制机制11. Chroot 特性12. 会话管理13. 服务器角色14. Zookeeper 下 Server ...

    03-05-08-zookeeper源码之watcher原理分析1

    //注册监听//修改节点的值触发监ZooKeeper API 的初始化过程转载请注明《咕泡学院》,建议自己分析一遍在创建一个 ZooKeeper 客户端对象实例

    zookeeper开源客户端ZkClient使用

    ZkClient是Github上一个开源的ZooKeeper客户端。ZkClient在ZooKeeper原生 API接口之上进行了包装,是一个更加易用的ZooKeeper客户端。同时,ZkClient在内部实现了诸如Session超时重连、Watcher反复注册等功能。

    thrift-zookeeper-rpc

    3.关于Failover/LoadBalance,由于zookeeper的watcher,当服务端不可用是及时通知客户端,并移除不可用的服务节点,而LoadBalance有很多算法,这里我们采用随机加权方式,也是常有的负载算法,至于其他的算法介绍...

    zookeeper开源客户端Curator

    Curator是Netflix公司开源的一套ZooKeeper客户端框架,Curator解决了很多ZooKeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等,实现了Fluent风格的API接口,目前已经...

    支持.Net Core的ZooKeeper异步客户端.zip

    该项目使用了 Apache ZooKeeper .NET async Client 组件,除提供了基本的zk操作,还额外封装了常用的功能以便让.net开发者更好的使用zookeeper。 提供的功能 session过期重连 永久watcher 递归删除...

    zookeeper淘宝实现的监控

    用于zookeeper写日志的目录要有足够大小,并且强烈建议在单独的磁盘(挂载点)上,这是影响ZK性能最大因素之一。 连接数。 注册的Watcher数。 ZNode是否可读,可写。 ZK事件通知的延时是否过大。 围绕以上几点展开,...

    Zookeeper面试题1

    1. 一次性 无论是服务端还是客户端,一旦一个 Watcher 被 触 发 ,Zookeeper 都会将其从相应的存 2. 客户端串行执行 客户端 Watche

    分布式协调工具-ZooKeeper实现动态负载均衡

    HRegionServer也会把自己以临时节点(Ephemeral)的方式注册到Zookeeper中,使得HMaster可以随时感知到各个HRegionServer的存活状态,同时,一旦HMaster出现问题,会重新选举出一个HMaster来运行,从而避免了HMaster...

    hornsey#ARTS#W3-zookeeper应用场景简述1

    配置维护大型分布式场景中,对相同配置的集群服务器集中进行配置管理,各服务器在zookeeper中注册watcher监听,发布者更新配置后,zookeeper向订

    分布式专题-04分布式协调服务之Zookeeper实践及与原理分析

    目录导航前言数据存储基于Java API初探zookeeper的使用事件机制如何注册事件机制watcher 事件类型什么样的操作会产生什么类型的事件呢?事务的实现原理深入分析Watcher机制的实现原理ClientCnxn 初始化客户端通过 ...

    zookeeper客户端Java代码示例.zip

    通过java客户端创建zk节点,变更节点,利用zk的watcher机制测试zk集群下的数据一致性,事务锁等机制。

    ZooKeeper分布式系统协调-其他

    Zookeeper使用Watcher察觉事件信息,当客户端接收到事件信息,比如连接超时,节点数据改变,子节点改变,可以调用相应的行为来处理数据。Zookeeper的Wiki页面展示了如何使用Zookeeper来处理事件通知,队列,优先队列...

Global site tag (gtag.js) - Google Analytics