在使用zookeper的时候一般不使用原生的API,Curator,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等等。

Curator包含了几个包:

  • curator-framework:对zookeeper的底层api的一些封装
  • curator-client:提供一些客户端的操作,例如重试策略等
  • curator-recipes:封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等

Maven依赖:

        <dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.12.0</version>
</dependency>

====================基本的API==============

1.创建会话

(1)静态工厂创建会话

源码如下:

    public static CuratorFramework newClient(String connectString, RetryPolicy retryPolicy)
{
return newClient(connectString, DEFAULT_SESSION_TIMEOUT_MS, DEFAULT_CONNECTION_TIMEOUT_MS, retryPolicy);
}
/**
* Create a new client
*
* @param connectString list of servers to connect to
* @param sessionTimeoutMs session timeout
* @param connectionTimeoutMs connection timeout
* @param retryPolicy retry policy to use
* @return client
*/
public static CuratorFramework newClient(String connectString, int sessionTimeoutMs, int connectionTimeoutMs, RetryPolicy retryPolicy)
{
return builder().
connectString(connectString).
sessionTimeoutMs(sessionTimeoutMs).
connectionTimeoutMs(connectionTimeoutMs).
retryPolicy(retryPolicy).
build();
}

测试代码:采用4个参数的方法

    private static CuratorFramework getClient() {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
return CuratorFrameworkFactory.newClient("localhost:2181", 5000, 3000, retryPolicy);
}

参数解释:

connectString: 链接 URL

sessionTimeoutMs: 会话超时时间,单位毫秒,默认60000ms

connectionTimeoutMs:    连接创建超时时间,单位毫秒,默认60000ms

retryPolicy:  重试策略,内建有四种重试策略,也可以自行实现RetryPolicy接口

1.RetryUntilElapsed(int maxElapsedTimeMs, int sleepMsBetweenRetries)
以sleepMsBetweenRetries的间隔重连,直到超过maxElapsedTimeMs的时间设置
2.RetryNTimes(int n, int sleepMsBetweenRetries)
指定重连次数
3.RetryOneTime(int sleepMsBetweenRetry)
重连一次,简单粗暴
4.ExponentialBackoffRetry
ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries)
ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries, int maxSleepMs)
时间间隔 = baseSleepTimeMs * Math.max(1, random.nextInt(1 << (retryCount + 1)))

(2)第二种方法:

    private static CuratorFramework getClient() {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.builder().connectString(URL)
.sessionTimeoutMs(5000).connectionTimeoutMs(5000).retryPolicy(retryPolicy).build();
return client;
}

(3)创建包含隔离命名空间的会话(下面也基于这种方式)

  为了实现不同的Zookeeper业务之间的隔离,需要为每个业务分配一个独立的命名空间(NameSpace),即指定一个Zookeeper的根路径。如果设置了该值,那么该客户端对Zookeeper上的数据节点的操作都是基于该目录进行的。
    private static CuratorFramework getClient() {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.builder().connectString(URL).sessionTimeoutMs(5000)
.connectionTimeoutMs(5000).retryPolicy(retryPolicy).namespace("curator").build();
return client;
}

得到会话之后,调用   client.start();   即可启动客户端。

原来zookeper数据结构如下:

关闭会话的方法如下:(必须在开启之后在关闭,否则会报非法状态异常)

client.close();

或者:

CloseableUtils.closeQuietly(client);

2.创建节点

  这个可以递归创建父节点并不抛出异常;指定节点类型(临时、顺序、临时永久),默认是永久

        CuratorFramework client = getClient();
client.start();
// 创建普通节点(默认是持久节点),内容为空
client.create().forPath("/t1");
// 创建普通节点(默认是持久节点)
client.create().forPath("/t2", "123456".getBytes());
// 创建永久顺序节点
client.create().withMode(CreateMode.PERSISTENT_SEQUENTIAL).forPath("/t3", "123456".getBytes());
// 地柜创建,如果父节点不存在也会创建
client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT_SEQUENTIAL)
.forPath("/t4/t41/t411", "123456".getBytes());

结果:

3.删除节点

  也可以递归删除。当然下面的多个流式接口可以随意组合。

        CuratorFramework client = getClient();
client.start();
// 删除子节点,只能删除叶子节点
client.delete().forPath("/t2");
// 递归删除
client.delete().deletingChildrenIfNeeded().forPath("/t4/t41");
// 指定版本进行删除
client.delete().withVersion(0).forPath("/t1");
// 强制删除。guaranteed()接口是一个保障措施,只要客户端会话有效,那么Curator会在后台持续进行删除操作,直到删除节点成功。
client.delete().guaranteed().forPath("/t30000000002");

结果:

4.读取节点数据---可以注册监听

        // 读取数据不获取stat
byte[] forPath = client.getData().forPath("/t4");
System.out.println(new String(forPath, "UTF-8")); // 读取数据且获取stat
Stat stat = new Stat();
byte[] forPath2 = client.getData().storingStatIn(stat).forPath("/t4");
System.out.println(new String(forPath2, "UTF-8"));
System.out.println(stat); // 注册观察者,当节点变动时触发
byte[] data = client.getData().usingWatcher(new Watcher() {
@Override
public void process(WatchedEvent event) {
System.out.println(event.getType());
}
}).forPath("/t4");
System.out.println("/t4: " + new String(data));

5.更新数据节点数据

        // 更新数据,返回的是stat
Stat forPath = client.setData().forPath("/t4", "data".getBytes()); // 更新一个节点的数据内容,强制指定版本进行更新
Stat stat = new Stat();
client.getData().storingStatIn(stat).forPath("/t4");
Stat forPath2 = client.setData().withVersion(stat.getVersion()).forPath("/t4", "data222".getBytes());

6. 检查节点是否存在

        Stat forPath = client.checkExists().forPath("/t4");
if (forPath != null) {
System.out.println("exists");
} else {
System.out.println("not exists");
}

7. 获取某个节点的所有子节点路径--这个获取的是子节点的名称且不带/

        List<String> forPath = client.getChildren().forPath("/");
System.out.println(forPath);

结果:

[t4]

8.事务

  允许作为一个原子操作进行提交。

        // inTransaction( )方法开启一个ZooKeeper事务.可以复合create, setData, check, and/or delete 等操作然后调用commit()作为一个原子操作提交
client.inTransaction().
check().forPath("/t4").
and().
create().withMode(CreateMode.EPHEMERAL).forPath("/t3", "data".getBytes()).
and().
setData().forPath("/t3", "data2".getBytes()).
and().
commit();

9.  异步接口

  上面提到的创建、删除、更新、读取等方法都是同步的,Curator提供异步接口,引入了BackgroundCallback接口用于处理异步接口调用之后服务端返回的结果信息。
  BackgroundCallback接口中一个重要的回调值为CuratorEvent,里面包含事件类型、响应码和节点的详细信息。

CuratorEventType:

响应码(#getResultCode())

如下:

        client.create().inBackground(new BackgroundCallback() {
@Override
public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
System.out.println(curatorEvent.getType() + " " + curatorEvent.getResultCode());
}
}, Executors.newFixedThreadPool(2)).forPath("/t2", "测试值".getBytes());

注意:    如果#inBackground()方法不指定executor,那么会默认使用Curator的EventThread去进行异步处理。

====================监听机制==============

  Curator的监听实现是对zookeeper原生监听方法的高级封装,主要体现在两点:监听重复注册,事件发生信息。而且监听事件返回详细的信息,如变动的节点信息,节点的value等。

  Curator 提供了3个接口:PathChildrenCacheListener、 NodeCache、TreeCache。三个接口都可以对一个不存在的节点进行监听。

1.   PathChildrenCache

  对指定的路径节点的一级子目录进行监听,不对该节点的操作进行监听,对其子目录的节点进行增、删、改的操作监听。

  如果监听的节点不存在会创建节点,如果节点是多级目录会递归创建,节点删除之后监听事件会失效。

如下:

    /**
*
* @param client
* @throws Exception
*/
private static void setListenterThreeOne(CuratorFramework client) throws Exception {
PathChildrenCache childrenCache = new PathChildrenCache(client, "/t4", true);
PathChildrenCacheListener childrenCacheListener = new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
ChildData data = event.getData();
switch (event.getType()) {
case CHILD_ADDED:
System.out.println("CHILD_ADDED : " + data.getPath() + " 数据:" + data.getData());
break;
case CHILD_REMOVED:
System.out.println("CHILD_REMOVED : " + data.getPath() + " 数据:" + data.getData());
break;
case CHILD_UPDATED:
System.out.println("CHILD_UPDATED : " + data.getPath() + " 数据:" + data.getData());
break;
default:
break;
}
}
}; // 在注册监听器的时候,如果传入此参数,当事件触发时,逻辑由线程池处理。如果不传会采用默认的线程池
ExecutorService pool = Executors.newFixedThreadPool(2);
// childrenCache.getListenable().addListener(childrenCacheListener);
childrenCache.getListenable().addListener(childrenCacheListener, pool);
// 设置监听模式
childrenCache.start(StartMode.BUILD_INITIAL_CACHE);
}

 StartMode:初始化方式

  POST_INITIALIZED_EVENT:异步初始化。初始化后会触发事件。如果节点不存在会创建节点。如果节点下面有子节点会触发CHILD_ADDED事件。
  NORMAL:异步初始化。如果节点不存在会创建节点。如果节点下面有子节点会触发CHILD_ADDED事件。
  BUILD_INITIAL_CACHE:同步初始化。如果节点不存在会创建节点。如果节点下面有子节点会触发CHILD_ADDED事件。

2.NodeCache

  对一个节点进行监听,监听事件包括指定的路径节点的增、删、改的操作。

  可以对一个不存在的节点进行监控,当节点创建之后会触发对应事件;节点被删除并且重建之后事件也仍然。

    // Node Cache 监控本节点的变化情况 连接 目录 是否压缩
// 监听本节点的变化 节点可以进行修改操作 删除节点后会再次创建(空节点)
private static void setListenterThreeTwo(CuratorFramework client) throws Exception {
ExecutorService pool = Executors.newCachedThreadPool();
// 设置节点的cache
final NodeCache nodeCache = new NodeCache(client, "/t5", false);
nodeCache.getListenable().addListener(new NodeCacheListener() {
@Override
public void nodeChanged() throws Exception {
System.out.println("the test node is change and result is :");
System.out.println("path : " + nodeCache.getCurrentData().getPath());
System.out.println("data : " + new String(nodeCache.getCurrentData().getData()));
System.out.println("stat : " + nodeCache.getCurrentData().getStat());
}
});
nodeCache.start();
}

3.TreeCache

  监控指定节点和节点下的所有的节点的变化--无限监听 ,也就是可以监听子孙目录。

  可以对一个不存在的节点进行监控,当节点创建之后会触发对应事件;节点被删除并且重建之后事件也仍然。

    // 监控 指定节点和节点下的所有的节点的变化--无限监听
private static void setListenterThreeThree(CuratorFramework client) throws Exception {
// 设置节点的cache
TreeCache treeCache = new TreeCache(client, "/t5");
// 设置监听器和处理过程
treeCache.getListenable().addListener(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:
System.out.println("NODE_ADDED : " + data.getPath() + " 数据:" + new String(data.getData()));
break;
case NODE_REMOVED:
System.out.println("NODE_REMOVED : " + data.getPath() + " 数据:" + new String(data.getData()));
break;
case NODE_UPDATED:
System.out.println("NODE_UPDATED : " + data.getPath() + " 数据:" + new String(data.getData()));
break; default:
break;
}
} else {
System.out.println("data is null : " + event.getType());
}
}
});
// 开始监听
treeCache.start();
}

补充:上面的三个接口在设置监听器的时候都可以传入自定义的线程池,也可不传,如下:

        // 在注册监听器的时候,如果传入此参数,当事件触发时,逻辑由线程池处理。如果不传会采用默认的线程池
ExecutorService pool = Executors.newFixedThreadPool(2);
// childrenCache.getListenable().addListener(childrenCacheListener);
childrenCache.getListenable().addListener(childrenCacheListener, pool);

Zookeeper客户端Curator基本API的更多相关文章

  1. zookeeper(六):Zookeeper客户端Curator的API使用详解

    简介 Curator是Netflix公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,包括连接重连.反复注册Watcher和NodeExistsEx ...

  2. Zookeeper客户端Curator使用详解

    Zookeeper客户端Curator使用详解 前提 最近刚好用到了zookeeper,做了一个基于SpringBoot.Curator.Bootstrap写了一个可视化的Web应用: zookeep ...

  3. 转:Zookeeper客户端Curator使用详解

    原文:https://www.jianshu.com/p/70151fc0ef5d Zookeeper客户端Curator使用详解 前提 最近刚好用到了zookeeper,做了一个基于SpringBo ...

  4. 八:Zookeeper开源客户端Curator的api测试

    curator是Netflix公司开源的一套ZooKeeper客户端,Curator解决了很多ZooKeeper客户端非常底层的细节开发工作.包括连接重连,反复注册Watcher等.实现了Fluent ...

  5. Zookeeper客户端Curator的使用,简单高效

    Curator是Netflix公司开源的一个Zookeeper客户端,与Zookeeper提供的原生客户端相比,Curator的抽象层次更高,简化了Zookeeper客户端的开发量. 1.引入依赖: ...

  6. 7.5 zookeeper客户端curator的基本使用 + zkui

    使用zookeeper原生API实现一些复杂的东西比较麻烦.所以,出现了两款比较好的开源客户端,对zookeeper的原生API进行了包装:zkClient和curator.后者是Netflix出版的 ...

  7. 聊聊、Zookeeper 客户端 Curator

    [Curator]   和 ZkClient 一样,Curator 也是开源客户端,Curator 是 Netflix 公司开源的一套框架. <dependency> <groupI ...

  8. Zookeeper客户端 CuratorFramework使用

    CuratorFramework使用 跟着实例学习ZooKeeper的用法: Curator框架应用 ZooKeeper客户端Curator使用一 创建连接

  9. Zookeeper之Curator(1)客户端基本的创建,删除,更新,查找操作api

    Curator Framework提供了简化使用zookeeper更高级的API接口.它包涵很多优秀的特性,主要包括以下三点: 自动连接管理:自动处理zookeeper的连接和重试存在一些潜在的问题: ...

随机推荐

  1. 怎样删除windows server back 备份副本文件

    我用的服务器是windows server 2012 下面说明 第一步:打开windows powershell 第二步:输入命令   DISKSHADOW 第二步:输入 delete shadows ...

  2. 格式化MYSQL时间戳函数FROM_UNIXTIME

    对MYSQL没有进行过深入的研究,基础知识匮乏,一遇到问题只能手册,看来要把MYSQL的学习安排进时间表了. 函数:FROM_UNIXTIME作用:将MYSQL中以INT(11)存储的时间以" ...

  3. ES6(promise)_解决回调地狱初体验

    一.前言 通过这个例子对promise解决回调地狱问题有一个初步理解. 二.主要内容 1.回调地狱:如下图所示,一个回调函数里面嵌套一个回调函数,这样的代码可读性较低也比较恶心 2.下面用一个简单的例 ...

  4. bzoj3991 LCA + set

    https://www.lydsy.com/JudgeOnline/problem.php?id=3991 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有 ...

  5. Python对象的创建和赋值

    创建类 类的定义以关键字class开头,之后跟着一个名字(用户定义)来标识这个类,并且以冒号结尾.类的内容以缩进(4个空格)表示,如下例的pass表示什么事情也不做. Python命名规则(以字母或者 ...

  6. RHCE基础环境系统的搭建

    RHCE基础环境系统的搭建 安装前提: 安装的时候对系统和硬件的要求: 红帽系统安装队系统的要求:Windows操作系统选择64位的内存至少6GCPU需要支持虚拟化技术在做红帽系统实验的时候,把360 ...

  7. 如何修改Tomcat的默认项目发布路径

    tomcat默认的项目发布目录是/webapp/ROOT,如果想自定义发布目录,应该怎么办呢? 修改配置文件 首先,修改$tomcat/conf/server.xml文件. 在server.xml文件 ...

  8. JAVA核心技术I---JAVA基础知识(文件系统及java文件基本操作)

    一:文件概述 文件系统是由OS(操作系统)管理的 文件系统和Java进程是平行的,是两套系统 文件系统是由文件夹和文件递归组合而成 文件目录分隔符 –Linux/Unix 用/隔开 –Windows用 ...

  9. UVA - 1401 | LA 3942 - Remember the Word(dp+trie)

    https://vjudge.net/problem/UVA-1401 题意 给出S个不同的单词作为字典,还有一个长度最长为3e5的字符串.求有多少种方案可以把这个字符串分解为字典中的单词. 分析 首 ...

  10. 常用Java数据库连接池

    概述 在这里所谓的数据库连接是指通过网络协议与数据库服务之间建立的TCP连接.通常,与数据库服务进行通信的网络协议无需由应用程序本身实现,原因有三: 实现复杂度大,需要充分理解和掌握相应的通信协议. ...