Curator简介
curator是Netflix公司开源的一套Zookeeper客户端框架,和ZKClient一样,Curator解决了很多 Zookeeper客户端非常底层的细节开发工作,包括连接重连,反复注册Watcher和NodeExistsException异常等,是最流行的Zookeeper客户端之一,从编码风格上来讲,它提供了基于Fluent的编程风格支持
添加依赖
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
创建会话
public class CreateSession {
// 创建会话
public static void main(String[] args) {
//方式1 不使用fluent编程风格
RetryPolicy exponentialBackoffRetry = new ExponentialBackoffRetry(1000, 3);
CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("127.0.0.1:2181", exponentialBackoffRetry);
curatorFramework.start();
System.out.println("会话被建立了");
//方式2 不使用fluent编程风格
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
CuratorFramework curatorFramework1 = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy);
curatorFramework1.start();
//方式3 使用fluent编程风格,上面两种底层编码都是通过这种方式
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("127.0.0.1:2181")
.sessionTimeoutMs(50000)
.connectionTimeoutMs(30000)
.retryPolicy(exponentialBackoffRetry)
.namespace("base") // 独立的命名空间 /base
.build();
client.start();
System.out.println("会话2创建了");
}
}
参数说明
- connectString : zk的server地址,多个server之间用英文逗号隔开
- connectionTimeoutMs:连接超时时间,默认15秒
- sessionTimeoutMs:会话超时时间,默认60秒
- retryPolicy:失败重试策略
RetryPolicy说明
public interface RetryPolicy
{
/**
*
* @param retryCount 已经重试的次数,如果是第一次,那么改值为0
* @param elapsedTimeMs 从第一次尝试开始已经花费的时间
* @param 用于sleep指定时间。不建议使用Thread.sleep()操作
* @return true/false
*/
public boolean allowRetry(int retryCount, long elapsedTimeMs, RetrySleeper sleeper);
}
重试策略实现方式主要有以下六种,参数说明如下
/**
* 1.baseSleepTimeMs 初始sleep时间,用于计算之后的每次重试的sleep时间,
* 计算公式当前sleep时间=baseSleepTimeMs*Math.max(1,random.nextInt(1<<(retryCount+1)))
* 2.maxRetries 最大重试次数
* 3.maxSleepMs 最大sleep时间,如果上述的当前sleep时间计算出来比这个大,那么sleep用这个时间,默认的最大时间是Integer.MAX_VALUE毫秒
*/
RetryPolicy exponentialBackoffRetry = new ExponentialBackoffRetry(1000, 3, 1000);
//继承ExponentialBackoffRetry,参数含义一样
RetryPolicy boundedExponentialBackoffRetry = new BoundedExponentialBackoffRetry(1000, 2000, 3);
//一直重试,参数retryIntervalMs:间隔时间
RetryPolicy retryForever = new RetryForever(1000);
//重试固定次数,参数sleepMsBetweenRetries:重试间隔sleep时间
RetryPolicy retryNTimes = new RetryNTimes(2, 1000);
//重试一次,参数sleepMsBetweenRetry:重试间隔sleep时间
RetryPolicy retryOneTime = new RetryOneTime(1000);
/**
* 指定重试最长花费的时间
* maxElapsedTimeMs 重试所花费的最大时间,到这个时间后就不重试了
* sleepMsBetweenRetries 重试间隔sleep时间
*/
RetryPolicy retryUntilElapsed = new RetryUntilElapsed(1000, 1000);
创建节点
public class CreateNote_curator {
public static void main(String[] args) throws Exception {
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("127.0.0.1:2181")
.sessionTimeoutMs(50000)
.connectionTimeoutMs(30000)
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
.namespace("base") // 独立的命名空间 /base
.build();
client.start();
System.out.println("会话创建了");
//创建一个初始内容为空的节点
client.create().forPath("/lg-curator-1");
//创建一个包含内容的节点
client.create().forPath("/lg-curator-2", "curator-2-test".getBytes());
//递归创建父节点,并设置节点类型和内容
String path = "/lg-curator/c1";
String s = client.create().creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT).forPath(path, "init".getBytes());
System.out.println("节点递归创建成功,该节点路径" + s);
}
}
删除节点
public class DeleteNote_curator {
public static void main(String[] args) throws Exception {
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("127.0.0.1:2181")
.sessionTimeoutMs(50000)
.connectionTimeoutMs(30000)
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
.namespace("base") // 独立的命名空间 /base
.build();
client.start();
System.out.println("会话创建了");
//删除一个节点
client.delete().forPath("/lg-curator-1");
//删除一个节点并递归删除其子节点
client.delete().deletingChildrenIfNeeded().forPath("/lg-curator-2");
//指定版本删除
client.delete().withVersion(1).forPath("/lg-curator-1");
//强制保证删除一个节点,只要客户端会话有效,那么curator会在后台持续进行删除,直到节点删除成功,
//比如遇到一些网络异常的情况,guaranteed强制删除会很有效果
client.delete().guaranteed().forPath("/lg-curator-1");
//组合各种条件进行删除
String path = "/lg-curator";
client.delete().deletingChildrenIfNeeded().withVersion(-1).forPath(path);
System.out.println("删除成功,删除的节点" + path);
}
}
获取数据
public class GetNote_curator {
public static void main(String[] args) throws Exception {
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("127.0.0.1:2181")
.sessionTimeoutMs(50000)
.connectionTimeoutMs(30000)
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
.namespace("base") // 独立的命名空间 /base
.build();
client.start();
System.out.println("会话创建了");
// 创建节点
String path = "/lg-curator/c1";
String s = client.create().creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT).forPath(path, "init".getBytes());
System.out.println("节点递归创建成功,该节点路径" + s);
// 获取节点数据内容
byte[] bytes = client.getData().forPath(path);
System.out.println("获取到的节点数据内容:" + new String(bytes));
// 获取节点状态信息
Stat stat = new Stat();
client.getData().storingStatIn(stat).forPath(path);
System.out.println("获取到的节点状态信息:" + stat);
}
}
更新数据
public class UpdateNote_curator {
public static void main(String[] args) throws Exception {
CuratorFramework client = CuratorFrameworkFactory.builder()
.connectString("127.0.0.1:2181")
.sessionTimeoutMs(50000)
.connectionTimeoutMs(30000)
.retryPolicy(new ExponentialBackoffRetry(1000, 3))
.namespace("base") // 独立的命名空间 /base
.build();
client.start();
System.out.println("会话创建了");
// 创建节点
String path = "/lg-curator/c1";
String s = client.create().creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT).forPath(path, "init".getBytes());
// 获取节点数据内容
byte[] bytes = client.getData().forPath(path);
System.out.println("获取到的节点数据内容:" + new String(bytes));
// 获取节点状态信息
Stat stat = new Stat();
client.getData().storingStatIn(stat).forPath(path);
System.out.println("获取到的节点状态信息:" + stat);
// 普通更新,为传入version参数,则更新当前最新版本
client.setData().forPath(path, "新内容".getBytes());
// 指定版本更新,如果version已经变更,则抛出异常
client.setData().withVersion(1).forPath(path);
// 更新节点内容
int version = client.setData().withVersion(stat.getVersion()).forPath(path, "修改内容1".getBytes()).getVersion();
System.out.println("当前的最新版本是" + version);
byte[] bytes2 = client.getData().forPath(path);
System.out.println("修改后的节点数据内容:" + new String(bytes2));
// 报BadVersionException异常,因为版本已经变更
client.setData().withVersion(stat.getVersion()).forPath(path, "修改内容2".getBytes());
}
}