前提:ZooKeeper版本:3.4.14 Curator版本:2.13.0
Curator是Netflix公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,是一个比较完善的ZooKeeper客户端框架,通过封装的一套高级API 简化了ZooKeeper的操作。
在Curator出现之前,我们可以通过zookeeper自带的客户端zkCli来访问,也可以通过Java API来对zookeeper中数据进行相关操作。为了更好的实现Java类操作zookeeper服务器,后来出现了Curator框架,非常的强大,目前已经是Apache的顶级项目,里面提供了更多丰富的操作。例如session超时重连、主从选举、分布式计数器、分布式锁等等适用于各种复杂的zookeeper场景的API封装。并且还提供了一套Fluent风格的操作API,Curator框架使用链式编程风格,易读性更强。
1.Java中使用,我们需要添加curator的maven依赖
curator-framework:对zookeeper的底层api的一些封装
curator-recipes:封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等
org.apache.curator
curator-framework
4.0.0
org.apache.curator
curator-recipes
4.0.0
2.完成对API的了解
1.获取Curator客户端会话连接(共有3种方式获取)
①使用工厂方法获取Curator客户端会话
public CuratorFramework getCuratorInstanceWithFactory(){
//配置重试策略(内建有四种重试策略,也可以自行实现RetryPolicy接口)
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
//使用默认的sessionTimeout和connectionTimeout获取连接
CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.204.201:2181,192.168.204.202:2181,192.168.204.203:2181", retryPolicy);
//启动Curator客户端
client.start();
return client;
}
构造方法:ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries) ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries,int maxSleepMs) |
|
参数名 | 说明 |
baseSleepTimeMs | 初始化Sleep时间 |
maxRetries | 最大重试次数 |
maxSleepMs(三个参数的构造方法) | 最大Sleep时间(默认值:2147483647) |
构造方法:CuratorFramework newClient(String connectString, RetryPolicy retryPolicy) CuratorFramework newClient(String connectString, int sessionTimeoutMs, int connectionTimeoutMs, RetryPolicy retryPolicy) |
|
参数名 | 说明 |
connectString | ZooKeeper服务地址(String,多个用逗号分隔) |
retryPolicy | 重试策略 |
sessionTimeoutMs | 会话超时时间(单位:ms 默认值:60000) |
connectionTimeoutMs | 连接超时时间(单位:ms 默认值:15000) |
②使用Fluent风格的API来创建会话
public CuratorFramework getCuratorInstanceWithFluent(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("192.168.204.201:2181,192.168.204.202:2181,192.168.204.203:2181")
.sessionTimeoutMs(40000)
.connectionTimeoutMs(10000)
.retryPolicy(retryPolicy)
.build();
client.start();
return client;
}
③创建带命名空间的会话
为了实现不同的Zookeeper业务之间的隔离,需要为每个业务分配一个独立的命名空间(namespace),即指定一个Zookeeper的根路径。在多个应用共用一个Zookeeper集群的场景下,这对于实现不同应用之间的相互隔离十分有意义
public CuratorFramework getCuratorInstanceWithNamespace(){
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("192.168.204.201:2181,192.168.204.202:2181,192.168.204.203:2181")
.sessionTimeoutMs(40000)
.connectionTimeoutMs(10000)
.retryPolicy(retryPolicy)
.namespace("/xxx")
.build();
client.start();
return client;
}
2.创建zNode数据节点(zookeeper节点)
节点数据类型分为如下4种:
public void createNode(CuratorFramework client){
try {
//1.创建一个节点(如果没有设置节点属性,默认为持久节点,未设值,我测试是一个:192.168.204.1,不应该是空吗)
client.create().forPath("/path");
//2.创建一个持久节点(指定值)
client.create().forPath("/path","value".getBytes());
//3.创建指定类型节点(临时节点)
//共有7种类型,常用的4种(PERSISTENT(持久),PERSISTENT_SEQUENTIAL(持久有序),EPHEMERAL(临时),EPHEMERAL_SEQUENTIAL(临时有序),CONTAINER,PERSISTENT_WITH_TTL,PERSISTENT_SEQUENTIAL_WITH_TTL)
client.create().withMode(CreateMode.EPHEMERAL).forPath("/path","value".getBytes());
//4.递归创建节点(creatingParentsIfNeeded()方法表示:如果父节点不存在,连带一起创建)
client.create().creatingParentsIfNeeded().forPath("/path/childPath","value".getBytes());
//这个creatingParentContainersIfNeeded()接口非常有用,因为一般情况开发人员在创建一个子节点必须判断它的父节点是否存在,如果不存在直接创建会抛出NoNodeException,使用creatingParentContainersIfNeeded()之后Curator能够自动递归创建所有所需的父节点。
} catch (Exception e) {
e.printStackTrace();
}
}
3.获取某个节点的数据
public void getNode(CuratorFramework client){
try {
//1.获取某个节点的数据
byte[] bytes = client.getData().forPath("/path1");
System.out.println(new String(bytes));
//2.获取某个节点的数据 && 同时获取该节点的Stat数据
Stat stat = new Stat();
byte[] bytes1 = client.getData().storingStatIn(stat).forPath("/path1");
System.out.println(stat);
System.out.println(new String(bytes1));
//3.获取某个节点下的所有子节点
List childs = client.getChildren().forPath("/");
System.out.println(Arrays.asList(childs));
} catch (Exception e) {
e.printStackTrace();
}
}
4.更新zNode节点的数据
public void setNodeData(CuratorFramework client){
try {
//1.更新节点数据内容
client.setData().forPath("/path","lzb".getBytes());
//2.指定版本数据内容更新(根据getData获取stat信息)
Stat stat = new Stat();
client.getData().storingStatIn(stat).forPath("/path");
client.setData().withVersion(stat.getVersion()).forPath("/path","lzb come on".getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
5.删除zNode节点数据
public void deleteNode(CuratorFramework client){
try {
//1.删除节点(该方法只能删除一个节点,如该节点有子节点,报错)
client.delete().forPath("/path");
//2.指定版本节点删除(根据getData获取stat信息)
Stat stat = new Stat();
client.getData().storingStatIn(stat).forPath("/path1");
client.delete().withVersion(stat.getVersion()).forPath("/path1");
//3.递归删除节点(有子节点的,递归全部删除)
client.delete().deletingChildrenIfNeeded().forPath("/path3");
//4.强制删除节点,直到删除成功
client.delete().guaranteed().forPath("/path11");
//guaranteed()接口是一个保障措施,只要客户端会话有效,那么Curator会在后台持续进行删除操作,直到删除节点成功。
} catch (Exception e) {
e.printStackTrace();
}
}
6.检查是否存在某个节点
public void checkExist(CuratorFramework client){
try {
//检查是否存在某个节点
Stat stat = client.checkExists().forPath("/path");
System.out.println(stat);
} catch (Exception e) {
e.printStackTrace();
}
}
Zookeeper原生支持通过注册Watcher来进行事件监听,但是开发者需要反复注册(Watcher只能单次注册单次使用)。Cache是Curator中对事件监听的包装,可以看作是对事件监听的本地缓存视图,能够自动为开发者处理反复注册监听。Curator提供了三种Watcher(Cache)来监听结点的变化。
1.PathChildrenCache 监听一个节点下子节点的创建、删除、更新操作
2.NodeCache 监听一个节点的更新和创建事件
3.TreeCache 综合PathChildrenCache和NodeCache的特性
1.PathChildrenCache监听(监听一个节点下子节点的创建、删除、更新操作)
/**
* PathChildrenCache 监听一个节点下子节点的创建、删除、更新操作
* @param client
* @param path
*/
public static void addListenerWithPathChildrenCache(CuratorFramework client,String path){
try {
PathChildrenCache pathChildrenCache = new PathChildrenCache(client,path,true);
PathChildrenCacheListener pathChildrenCacheListener = new PathChildrenCacheListener() {
public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
System.out.println("Receive Event:"+ pathChildrenCacheEvent.getType());
}
};
pathChildrenCache.getListenable().addListener(pathChildrenCacheListener);
pathChildrenCache.start(PathChildrenCache.StartMode.NORMAL);
} catch (Exception e) {
e.printStackTrace();
}
}
2.NodeCache监听(用于监听一个节点的更新和创建事件)
/**
* NodeCache 用于监听一个节点的更新和创建事件
* 当创建节点,或者更新节点信息时,会监听到
*/
public static void addListenerWithNodeCache(CuratorFramework client,String path){
try {
final NodeCache nodeCache = new NodeCache(client,path,false);
NodeCacheListener nodeCacheListener = new NodeCacheListener() {
public void nodeChanged() throws Exception {
System.out.println("Receive Event:"+nodeCache.getCurrentData().getPath());
}
};
nodeCache.getListenable().addListener(nodeCacheListener);
nodeCache.start();
} catch (Exception e) {
e.printStackTrace();
}
}
3.TreeCache综合节点监听(PathChildrenCache和NodeCache的特性)
/**
* TreeCache 综合节点监听事件(PathChildrenCache和NodeCache的特性)
* @param client
* @param path
*/
public static void addListenerWithTreeCache(CuratorFramework client,String path){
try {
TreeCache treeCache = new TreeCache(client,path);
TreeCacheListener treeCacheListener = new TreeCacheListener() {
public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
System.out.println(treeCacheEvent.getType() + "-->" + treeCacheEvent.getData().getPath());
}
};
treeCache.getListenable().addListener(treeCacheListener);
treeCache.start();
} catch (Exception e) {
e.printStackTrace();
}
}
Curator高级属性,感觉这位博主写的很棒。本篇就不做更多介绍,只做基本使用介绍。
请参考:Zookeeper客户端Curator使用详解