1、篇首语

curator是zookeeper的一个高级api开发包。封装了zookeeper众多的recipes,并且实现了一些新的recipes原语,最重要的是基于zookeeper提供的各种机制实现了更健壮的连接和异常处理。

本文将其中比较常用的一种recipe,就是cache。

2、各种Caches

cache是一种缓存机制,可以借助cache实现监听。

简单来说,cache在客户端缓存了znode的各种状态,当感知到zk集群的znode状态变化,会触发event事件,注册的监听器会处理这些事件。是不是很简单。

curator支持的cache种类有3种Path Cache,Node Cache,Tree Cache

1)Path Cache

Path Cache用来观察ZNode的子节点并缓存状态,如果ZNode的子节点被创建,更新或者删除,那么Path Cache会更新缓存,并且触发事件给注册的监听器。

Path Cache是通过PathChildrenCache类来实现的,监听器注册是通过PathChildrenCacheListener。

2)Node Cache

Node Cache用来观察ZNode自身,如果ZNode节点本身被创建,更新或者删除,那么Node Cache会更新缓存,并触发事件给注册的监听器。

Node Cache是通过NodeCache类来实现的,监听器对应的接口为NodeCacheListener。

3)Tree Cache

可以看做是上两种的合体,Tree Cache观察的是所有节点的所有数据。

3、下面给出一个例子。

1)这是在springboot中使用curator,先给出curator依赖pom

<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.8</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.9.1</version>
</dependency>

2)三种cache的实现

package com.dqa.prometheus.client.zookeeper;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.*;
import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.utils.CloseableUtils;
import org.apache.zookeeper.CreateMode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List; public class ZkClient {
private final Logger logger = LoggerFactory.getLogger(this.getClass()); private CuratorFramework client;
private NodeCache nodeCache;
private PathChildrenCache pathChildrenCache;
private TreeCache treeCache;
private String zookeeperServer;
private int sessionTimeoutMs;
private int connectionTimeoutMs;
private int baseSleepTimeMs;
private int maxRetries; public void setZookeeperServer(String zookeeperServer) {
this.zookeeperServer = zookeeperServer;
}
public String getZookeeperServer() {
return zookeeperServer;
}
public void setSessionTimeoutMs(int sessionTimeoutMs) {
this.sessionTimeoutMs = sessionTimeoutMs;
}
public int getSessionTimeoutMs() {
return sessionTimeoutMs;
}
public void setConnectionTimeoutMs(int connectionTimeoutMs) {
this.connectionTimeoutMs = connectionTimeoutMs;
}
public int getConnectionTimeoutMs() {
return connectionTimeoutMs;
}
public void setBaseSleepTimeMs(int baseSleepTimeMs) {
this.baseSleepTimeMs = baseSleepTimeMs;
}
public int getBaseSleepTimeMs() {
return baseSleepTimeMs;
}
public void setMaxRetries(int maxRetries) {
this.maxRetries = maxRetries;
}
public int getMaxRetries() {
return maxRetries;
} public void init() {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(baseSleepTimeMs, maxRetries);
client = CuratorFrameworkFactory.builder().connectString(zookeeperServer).retryPolicy(retryPolicy)
.sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs).build();
client.start();
} public void stop() {
if (client != null) CloseableUtils.closeQuietly(client);
if (pathChildrenCache != null) CloseableUtils.closeQuietly(pathChildrenCache);
if (nodeCache != null) CloseableUtils.closeQuietly(nodeCache);
if (treeCache != null) CloseableUtils.closeQuietly(treeCache);
} public CuratorFramework getClient() {
return client;
} /*
* 设置Path Cache, 监控本节点的子节点被创建,更新或者删除,注意是子节点, 子节点下的子节点不能递归监控
* 事件类型有3个, 可以根据不同的动作触发不同的动作
* 本例子只是演示, 所以只是打印了状态改变的信息, 并没有在PathChildrenCacheListener中实现复杂的逻辑
* @Param path 监控的节点路径, cacheData 是否缓存data
* 可重入监听
* */
public void setPathCacheListener(String path, boolean cacheData) {
try {
pathChildrenCache = new PathChildrenCache(client, path, cacheData);
PathChildrenCacheListener childrenCacheListener = new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) {
ChildData data = event.getData();
switch (event.getType()) {
case CHILD_ADDED:
logger.info("子节点增加, path={}, data={}", data.getPath(), data.getData());
break;
case CHILD_UPDATED:
logger.info("子节点更新, path={}, data={}", data.getPath(), data.getData());
break;
case CHILD_REMOVED:
logger.info("子节点删除, path={}, data={}", data.getPath(), data.getData());
break;
default:
break;
}
}
};
pathChildrenCache.getListenable().addListener(childrenCacheListener);
pathChildrenCache.start(StartMode.POST_INITIALIZED_EVENT);
} catch (Exception e) {
logger.error("PathCache监听失败, path=", path);
} } /*
* 设置Node Cache, 监控本节点的新增,删除,更新
* 节点的update可以监控到, 如果删除会自动再次创建空节点
* 本例子只是演示, 所以只是打印了状态改变的信息, 并没有在NodeCacheListener中实现复杂的逻辑
* @Param path 监控的节点路径, dataIsCompressed 数据是否压缩
* 不可重入监听
* */
public void setNodeCacheListener(String path, boolean dataIsCompressed) {
try {
nodeCache = new NodeCache(client, path, dataIsCompressed);
NodeCacheListener nodeCacheListener = new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
ChildData childData = nodeCache.getCurrentData();
logger.info("ZNode节点状态改变, path={}", childData.getPath());
logger.info("ZNode节点状态改变, data={}", childData.getData());
logger.info("ZNode节点状态改变, stat={}", childData.getStat());
}
};
nodeCache.getListenable().addListener(nodeCacheListener);
nodeCache.start();
} catch (Exception e) {
logger.error("创建NodeCache监听失败, path={}", path);
}
} /*
* 设置Tree Cache, 监控本节点的新增,删除,更新
* 节点的update可以监控到, 如果删除不会自动再次创建
* 本例子只是演示, 所以只是打印了状态改变的信息, 并没有在NodeCacheListener中实现复杂的逻辑
* @Param path 监控的节点路径, dataIsCompressed 数据是否压缩
* 可重入监听
* */
public void setTreeCacheListener(final String path) {
try {
treeCache = new TreeCache(client, path);
TreeCacheListener treeCacheListener = new TreeCacheListener() {
@Override
public void childEvent(CuratorFramework client, TreeCacheEvent event) throws Exception {
ChildData data = event.getData();
if(data != null){
switch (event.getType()) {
case NODE_ADDED:
logger.info("[TreeCache]节点增加, path={}, data={}", data.getPath(), data.getData());
break;
case NODE_UPDATED:
logger.info("[TreeCache]节点更新, path={}, data={}", data.getPath(), data.getData());
break;
case NODE_REMOVED:
logger.info("[TreeCache]节点删除, path={}, data={}", data.getPath(), data.getData());
break;
default:
break;
}
}else{
logger.info("[TreeCache]节点数据为空, path={}", data.getPath());
}
}
};
treeCache.getListenable().addListener(treeCacheListener);
treeCache.start();
} catch (Exception e) {
logger.error("创建TreeCache监听失败, path={}", path);
} }
}

3)configuration

init方法是初始化zookeeper client的操作

stop是停止zookeeper是的清理动作

package com.dqa.prometheus.configuration;

import com.xiaoju.dqa.prometheus.client.zookeeper.ZkClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class ZkConfiguration { @Value("${zookeeper.server}")
private String zookeeperServer;
@Value(("${zookeeper.sessionTimeoutMs}"))
private int sessionTimeoutMs;
@Value("${zookeeper.connectionTimeoutMs}")
private int connectionTimeoutMs;
@Value("${zookeeper.maxRetries}")
private int maxRetries;
@Value("${zookeeper.baseSleepTimeMs}")
private int baseSleepTimeMs; @Bean(initMethod = "init", destroyMethod = "stop")
public ZkClient zkClient() {
ZkClient zkClient = new ZkClient();
zkClient.setZookeeperServer(zookeeperServer);
zkClient.setSessionTimeoutMs(sessionTimeoutMs);
zkClient.setConnectionTimeoutMs(connectionTimeoutMs);
zkClient.setMaxRetries(maxRetries);
zkClient.setBaseSleepTimeMs(baseSleepTimeMs);
return zkClient;
} }

3)zk配置文件

其中最重要的应该是会话超时和重试机制了。

============== zookeeper ===================
zookeeper.server=10.93.21.21:,10.93.18.34:,10.93.18.35:
zookeeper.sessionTimeoutMs=
zookeeper.connectionTimeoutMs=
zookeeper.maxRetries=
zookeeper.baseSleepTimeMs=

zookeeper curator使用caches实现各种监听的更多相关文章

  1. ZooKeeper个人笔记之节点的监听

    create public String create(String path, byte[] data, List<ACL> acl, CreateMode createMode) th ...

  2. ZooKeeper(3.4.5) 使用Curator监听事件

    转载:http://www.mamicode.com/info-detail-494364.html 标签: ZooKeeper原生的API支持通过注册Watcher来进行事件监听,但是Watcher ...

  3. ZooKeeper(3.4.5) - 使用 Curator(2.7.0) 监听事件

    ZooKeeper原生的API支持通过注册Watcher来进行事件监听,但是Watcher通知是一次性的,因此开发过程中需要反复注册Watcher,比较繁琐.Curator引入了Cache来监听Zoo ...

  4. Zookeeper Curator 事件监听 - 秒懂

    目录 写在前面 1.1. Curator 事件监听 1.1.1. Watcher 标准的事件处理器 1.1.2. NodeCache 节点缓存的监听 1.1.3. PathChildrenCache ...

  5. 基于Zookeeper实现客户端动态监听服务器上下线

    一.在具体实现之前,先来了解一下Zookeeper的监听器的原理: 图中Main()线程作为客户端,当在主线程中创建Zookeeper客户端时,会默认创建两个子线程:Listener和connect, ...

  6. Zookeeper开源客户端Curator之事件监听详解

    Curator对Zookeeper典型场景之事件监听进行封装,提供了使用参考.这篇博文笔者带领大家了解一下Curator的实现方式. 引入依赖 对于Curator封装Zookeeper的典型场景使用都 ...

  7. 如何使用Curator监听zookeeper事件变化

    掌握zookeeper事件监听机制,非常重要,可以说是跨入了进阶的门槛,只有掌握了如何监听某个节点或路径,我们才能在节点变化后,做一些我们想做的事,包括: 1,配置文件同步 2,主从切换 3,分布式队 ...

  8. 8、Curator的监听机制

    原生的zookeeper的监听API所实现的方法存在一些缺点,对于开发者来说后续的开发会考虑的细节比较多. Curator所实现的方法希望摒弃原声API 的不足,是开发看起来更加的简单,一些重连等操作 ...

  9. Curator的监听机制

    原生的zookeeper的监听API所实现的方法存在一些缺点,对于开发者来说后续的开发会考虑的细节比较多. Curator所实现的方法希望摒弃原声API 的不足,是开发看起来更加的简单,一些重连等操作 ...

随机推荐

  1. 九度OJ 1006 ZOJ

    #include <iostream> #include <string> using namespace std; int getO(string str,int & ...

  2. 201521123091 《Java程序设计》第13周学习总结

    Java 第十三周总结 第十三周的作业. 目录 1.本章学习总结 2.Java Q&A 3.码云上代码提交记录及PTA实验总结 4.课后阅读 1.本章学习总结 1.1 以你喜欢的方式(思维导图 ...

  3. 201521123076《java程序设计》第四次总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. instanceof可以测试一个对象是否是某个类(或其父类),右边'is a?'左边关系. ...

  4. 201521123013 《Java程序设计》第13周学习总结

    1. 本周学习总结 2. 书面作业 Q1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? ping值 ...

  5. 201521123045 《JAVA程序设计》第1周学习总结

    1. 本周学习总结 学习了入门的java知识,知道了jdk.eclipse等基础软件,了解了如何编译最基础的java程序.知道了java的基本原理以及java的几种数据类型.掌握使用简单编译器编写ja ...

  6. Hyperledger Fabric 1.0 从零开始(五)——运行测试e2e

    3:运行测试e2e 3.1.运行fabric-samples的问题说明 该问题说明能够解决6.1.平台特定使用的二进制文件配置第一步的问题.可以选择继续阅读该说明,或者等参考到6.1小节时再反向阅读本 ...

  7. panda库------对数据进行操作---合并,转换,拼接

    >>> frame2 addr age name 0 beijing 12 zhang 1 shanghai 24 li 2 hangzhou 24 cao >>> ...

  8. Maven第二篇【Idea下使用Maven】

    详情可参照详细的Maven教程-Idea环境下 值得追加的是:在修改web.xml路径的时候,那篇博文并没有给出绝对的路径-这里可能有些人不知道怎么写.我给出来参考 X:\Users\ozc\Desk ...

  9. java基础知识2--String,StringBufffer,StringBuilder的区别

    String,StringBufffer,StringBuilder的区别 1.可变不可变方面 String类中使用字符数组保存字符串  ,final 修饰当然是不可变的,用String来操作字符串的 ...

  10. Eclipse读取含有extjs的项目文件时卡死或者编写ExtJS时卡

    新建一个Eclipse或MyEclipse项目时,关掉验证. 项目右键-->Properties-->Builders--> 不勾选(JavaScript Validator.Val ...