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. yum的初步了解与使用

    什么是yum Yum(Yellow dog Updater,Modified)是一个基于RPM包管理的字符前端软件包管理器.能够从指定的服务器自动下载RPM包并且安装,可解决软件包相关依赖性,并且一次 ...

  2. Markdown(editormd)语法解析成html

    我们在一些网站中可以见到一款网页编辑器--markdown: 这是一款功能强大的富文本编辑器,之前自己在网页上使用的时候遇到了一点点的问题,现在跟大家分享下 在我们写了文章之后是需要将内容保存到数据库 ...

  3. mysql中int(10)与int(11)有什么区别吗?

    先来看下面的图片 声明字段是int类型的那一刻起,int就是占四个字节,一个字节8位,也就是4*8=32,可以表示的数字个数是2的32次方(2^32 = 4 294 967 296个数字). 4 29 ...

  4. About Cheating and Plagiarism

    我先描述一下此次事件的具体经过.昨天3月15号的晚上十点,是第四次作业的deadline.在15号之前,只有五位同学提交了作业,而在临近deadline的这几个小时内密密麻麻地提交了二十多份作业.和第 ...

  5. 团队作业8----第二次项目冲刺(Beta阶段) 第六天

    BETA阶段冲刺第六天 1.小会议ing 2.每个人的工作 (1)昨天已完成的工作 重复部分可以用红色字体显示 (2) 今天计划完成的工作 (3) 工作中遇到的困难: 尤少辉:在测试的时候,当队友提出 ...

  6. 团队作业4——第一次项目冲刺(Alpha版本)2017.4.28

    2017.04.28 天气晴朗 东风3级. 时间:上午 9:35 ---10:10分 地点:陆大二楼 会议内容:实验室报修系统项目冲刺Alpha版的的最后一天,大家对现在项目的进程进行了讨论,阐述了各 ...

  7. 201521123097《Java程序设计》第三周学习总结

    1. 本周学习总结 2. 书面作业 1.代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; p ...

  8. Socket类 以及 ServerSocket类 讲解

    Socket类 套接字是网络连接的端点,套接字使应用可以从网络中读取数据,可以向网络中写入数据.不同计算机上的两个应用程序可以通过连接发送或接收字节流,以此达到相互通信的目的. 为了从一个应用程序向另 ...

  9. WEB中的敏感文件泄漏

    文件泄露, 根据泄漏的信息敏感程度, 在WEB漏洞中可以算是中危甚至高危的漏洞, 本篇文章就来 介绍下一些常见的泄漏, 主要分为由版本管理软件导致的泄露, 文件包含导致的泄露和配置错误导致的泄露. 版 ...

  10. New Features and changes of Ninject 3.3

    Ninject 3.3 beta1 has gone live. This release mainly focus on bug fix and platform update. Support . ...