`
agapple
  • 浏览: 1596023 次
  • 性别: 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- 简单例子

    为了更好地理解Watcher的使用,下面我们将通过一个简单的Java程序来创建一个Watcher并监听Zookeeper上的数据节点。 首先,我们需要在`pom.xml`中引入Zookeeper的依赖: ```xml &lt;groupId&gt;org.apache.zookeeper ...

    ZooKeeper典型使用场景

    ### ZooKeeper典型使用场景详解 #### 一、概述 ZooKeeper是一款开源的分布式协调服务框架,主要用于解决分布式系统中的数据一致性问题。它基于Paxos算法实现,确保了即使在网络分区的情况下,也能保证分布式环境下...

    第二课:zookeeper客户端使用与集群特性.docx

    本文将详细介绍 ZooKeeper 客户端的使用和集群特性,包括客户端简介、客户端连接参数说明、客户端 CRUD、客户端监听、集群架构说明、集群配置及参数说明、选举投票机制、主从复制机制等知识点。 一、客户端 API ...

    ZooKeeper的简单使用

    在实际使用中,ZooKeeper提供了丰富的API,如创建、删除、更新和读取ZNode,以及设置和触发Watcher。例如,`Demo1.java`和`Demo2.java`可能包含这样的示例代码: ```java import org.apache.zookeeper.*; public ...

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

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

    zookeeper 使用指导PDF

    通过学习和理解这些知识点,开发者和系统管理员能够更好地掌握Zookeeper的使用,从而在分布式系统中实现高效、可靠的协调和管理。无论你是初学者还是经验丰富的专业人士,这份"Zookeeper 使用指导"都将是你宝贵的...

    zookeeper-3.4.6_zookeeper_

    3. **事件通知**:Zookeeper提供watcher机制,允许客户端设置监听某个节点的变化,当节点状态发生变化时,Zookeeper会立即通知相关客户端,实现快速响应。 4. **会话管理**:Zookeeper维护客户端的会话状态,如果...

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

    在本文中,我们将深入探讨Zookeeper中的Watcher原理,这是一个关键特性,它允许客户端对Zookeeper中的数据变化进行实时监控。Watcher机制是Zookeeper提供的一种事件通知模型,它使得客户端能够及时响应Zookeeper中...

    zookeeper 3.8.4

    - **Watcher 事件监听**:Zookeeper 支持 Watcher 机制,允许客户端注册监听特定节点的变化,当节点发生变化时,Zookeeper 会触发回调通知客户端。 ### 2. ZooKeeper 的功能 - **命名服务**:为分布式组件提供唯一...

    ZooKeeper 客户端的使用(一)

    - **Watcher**:Watcher 是 ZooKeeper 中的一种通知机制,可以注册在 ZNode 上,当 ZNode 发生变化时,Watcher 将接收到通知事件。 ### 4. ZooKeeper 的一致性保证 ZooKeeper 提供了强一致性模型,确保数据在同一...

    zookeeper_javaAPI-main.zip

    在IT行业中,Zookeeper和Java API的结合使用是分布式系统管理的重要组成部分。Zookeeper是由Apache软件基金会开发的一个开源项目,它提供了一种高效且可靠的分布式协调服务,常用于配置管理、命名服务、集群管理和...

    zookeeper查看器

    5. **ZookeeperWatcher的使用** - **安装与启动**: 解压ZookeeperWatcher压缩包,按照官方文档或README文件进行配置和启动。 - **连接Zookeeper**: 输入Zookeeper服务器的连接地址和端口,建立连接。 - **操作...

    zookeeper-3.8.0安装包下载

    对于学习 Zookeeper 的学生或部署的工作人员,了解以下知识点至关重要: 1. 安装与配置:如何正确地安装 Zookeeper,包括修改配置文件、设置环境变量等。 2. 集群部署:如何配置多台机器组成 Zookeeper 集群,包括...

    zookeeper-3.4.13.zip

    - 使用Watcher时要注意避免死循环和资源耗尽的问题。 8. **Zookeeper的未来发展趋势**: - 随着微服务和云原生架构的发展,Zookeeper将在服务治理、分布式事务等领域发挥更大作用。 - 可能与Kubernetes等现代...

    zookeeper-3.4.8源码包

    2. Client:Zookeeper客户端,提供了丰富的API供应用使用,如创建、删除、更新、查询ZNode等操作。 3. ZNode:Zookeeper的数据模型,类似于文件系统的目录结构,每个节点称为ZNode,包含了数据、元数据和ACL(访问...

    zookeeper使用文档V1.0.0.pdf

    在解决Zookeeper使用中的常见问题时,例如关于Zookeeper init函数的使用、session失效问题、watcher设置和获取等,都需要对Zookeeper内部工作原理和API有充分的了解。在进行Zookeeper安装和配置时,应该参考官方文档...

    Zookeeper中文开发指南

    这个“Zookeeper中文开发指南”是针对开发人员和系统管理员的一份宝贵的资源,它涵盖了从基础概念到高级应用的所有关键知识点。 **一、Zookeeper基本概念** 1. **节点(Znode)**: ZooKeeper 的数据存储结构基于树...

    zookeeper客户端api使用

    本文将深入探讨ZooKeeper客户端API的使用方法和核心概念。 ### 1. 连接ZooKeeper 在使用ZooKeeper客户端API之前,首先需要建立与ZooKeeper服务器的连接。这通常通过`ZooKeeper`类的构造函数完成,传入服务器地址...

    VIP-02 Zookeeper客户端使用与集群特性(1)

    ### VIP-02 Zookeeper客户端使用与集群特性(1) #### Curator介绍 Curator是Netflix公司开源的一个针对ZooKeeper的高级Java客户端框架。它不仅简化了ZooKeeper的使用,还提供了丰富的抽象和工具类,使得开发者能够...

    zookeeper版本为zookeeper-3.4.10.tar.gz

    在使用Zookeeper时,需要注意监控Zookeeper的服务状态,定期备份数据,以及定期升级以获取最新的安全修复和功能增强。此外,对于高可用性需求,通常会部署多个Zookeeper节点构成一个集群,以确保服务的连续性和数据...

Global site tag (gtag.js) - Google Analytics