Java原生API操作ZooKeeper可参看:
Java原生API操作Zookeeper(一)
Java原生API操作Zookeeper(二)
相关内容:
基于Curator操作ZooKeeper(二)-Watcher操作
基于Curator操作ZooKeeper(二)-Watcher操作-补充TreeCache
基于Curator操作ZooKeeper(三)-Curator整合Spring
Java原生操作API有以下几个不足之处:
一般企业操作ZooKeeper的客户端都会使用Apache Curator。和ZkClient一样,Curator解决了很ZooKeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等,目前已经成为了Apache的顶级项目,是全世界范围内使用最广泛的ZooKeeper客户端之一。
除了封装一些开发人员不需要特别关注的底层细节之外,Curator还在ZooKeeperAPI的基础上进行了包装,提供了一套易用性和可读性更强的Fluent风格的客户端API框架。除此之外,Curator中还提供了ZooKeeper各种应用场景(Recipe,如共享锁服务、Master选举机制和分布式计数器等)的抽象封装。
org.apache.zookeeper
zookeeper
3.4.11
org.apache.curator
curator-framework
4.0.0
org.apache.curator
curator-recipes
4.0.0
其实curator-framwork中是有ZooKeeper的依赖的:
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
public class CuratorOperator {
public CuratorFramework client = null;
public static final String zkServerPath = "192.168.220.135:2181,192.168.220.136:2181,192.168.220.137:2181";
/**
* 实例化zk客户端
*/
public CuratorOperator() {
/**
* 同步创建zk示例,原生api是异步的
*
* curator链接zookeeper的重试策略:
*
* 1>ExponentialBackoffRetry【推荐】
* baseSleepTimeMs:初始sleep时间(ms)
* maxRetries:最大重试次数,超过时间就不链接了
* maxSleepMs:最大重试时间(ms)
*
* 给定一个初始sleep时间base5leep丁imeMs,在这个基础上结合重试次数,通过以下公式计算出当前需要sleep的时间:
当前sleep时间=baseSleepTimeMs*Math.max(1, random.nextInt(1<<(retryCount+1)))
可以看出,随着重试次数的增加,计算出的sleep时间会越来越大。如果该sleep时间在maxSleepMs的范围之内,那么就使用该sleep时间,否则使用maxSleepMs。另外,
maxRetries参数控制了最大重试次数,以避免无限制的重试。
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);
/**
* curator链接zookeeper的策略:
* 2>RetryNTimes【推荐】
* n:重试的次数
* sleepMsBetweenRetries:每次重试间隔的时间(ms)
*/
// RetryPolicy retryPolicy = new RetryNTimes(3, 5000);
/**
* curator链接zookeeper的策略:
* 3>RetryOneTime
* sleepMsBetweenRetry:只重试一次,重试间隔的时间
*/
// RetryPolicy retryPolicy2 = new RetryOneTime(3000);
/**
* 4>
* 永远重试,不推荐使用
*/
// RetryPolicy retryPolicy3 = new RetryForever(retryIntervalMs)
/**
* curator链接zookeeper的策略:
* 5>RetryUntilElapsed
* maxElapsedTimeMs:最大重试时间
* sleepMsBetweenRetries:每次重试间隔
* 重试时间超过maxElapsedTimeMs后,就不再重试
*/
// RetryPolicy retryPolicy4 = new RetryUntilElapsed(2000, 3000);
//创建客户端
client = CuratorFrameworkFactory.builder() //builder
.connectString(zkServerPath)
.sessionTimeoutMs(10000) //session超时时间
.retryPolicy(retryPolicy) //重试策略
.build();
/**
* CuratorFrameworkFactory工厂在创建出一个客户端CuratorFramework实例之后,实质上并没有完成会话的创建,而是需要调用
CuratorFramework的sta rt)方法来完成会话的创建。
*/
client.start();
}
/**
*
* @Description: 关闭zk客户端连接
*/
public void closeZKClient() {
if (client != null) {
this.client.close();
}
}
public static void main(String[] args) throws Exception {
// 实例化
CuratorOperator cto = new CuratorOperator();
boolean isZkCuratorStarted = cto.client.isStarted();
System.out.println("当前客户的状态:" + (isZkCuratorStarted ? "连接中" : "已关闭"));
Thread.sleep(3000);
cto.closeZKClient();
boolean isZkCuratorStarted2 = cto.client.isStarted();
System.out.println("当前客户的状态:" + (isZkCuratorStarted2 ? "连接中" : "已关闭"));
}
}
运行结果:
在3.2.0及其之后版本的ZooKeeper中,添加了“Chroot”特性,该特性允许每个客户端为自己设置一个命名空间 ( Namespace )。如果一个ZooKeeper客户端设置了Chroot,那么该客户端对服务器的任何操作,都将会被限制在其自己的命名空间下。
举个例子来说,如果我们希望为应用X分配/apps/X下的所有子节点,那么该应用可以将其所有ZooKeeper客户端的Chroot设置为/apps/X的。一旦设置了Chroot之后,那么对这个客户端来说,所有的节点路径都以/apps/X为根节点,它和ZooKeeper发起的所有请求中相关的节点路径,都将是一个相对路径—相对于/apps/X的路径。例如通过ZooKeeper客户端API创建点/test_chroot,那么实际上在服务端被创建的节点是/apps/X/test_ chroot,通过设置Chroot,我们能够将一个客户端应用与ZooKeeper服务端
的一棵子树相对应,在那些多个应用共用一个ZooKeeper集群的场景下,这对于实现不同应用之间的相互隔离非常有帮助。
新增节点:
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
public class CuratorOperator {
public CuratorFramework client = null;
public static final String zkServerPath = "192.168.220.135:2181,192.168.220.136:2181,192.168.220.137:2181";
/**
* 实例化zk客户端
*/
public CuratorOperator() {
/**
* 同步创建zk示例,原生api是异步的
*
* curator链接zookeeper的重试策略:
*
* 1>ExponentialBackoffRetry【推荐】
* baseSleepTimeMs:初始sleep时间(ms)
* maxRetries:最大重试次数,超过时间就不链接了
* maxSleepMs:最大重试时间(ms)
*
* 给定一个初始sleep时间base5leep丁imeMs,在这个基础上结合重试次数,通过以下公式计算出当前需要sleep的时间:
当前sleep时间=baseSleepTimeMs*Math.max(1, random.nextInt(1<<(retryCount+1)))
可以看出,随着重试次数的增加,计算出的sleep时间会越来越大。如果该sleep时间在maxSleepMs的范围之内,那么就使用该sleep时间,否则使用maxSleepMs。另外,
maxRetries参数控制了最大重试次数,以避免无限制的重试。
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);
/**
* curator链接zookeeper的策略:
* 2>RetryNTimes【推荐】
* n:重试的次数
* sleepMsBetweenRetries:每次重试间隔的时间(ms)
*/
// RetryPolicy retryPolicy = new RetryNTimes(3, 5000);
/**
* curator链接zookeeper的策略:
* 3>RetryOneTime
* sleepMsBetweenRetry:只重试一次,重试间隔的时间
*/
// RetryPolicy retryPolicy2 = new RetryOneTime(3000);
/**
* 4>
* 永远重试,不推荐使用
*/
// RetryPolicy retryPolicy3 = new RetryForever(retryIntervalMs)
/**
* curator链接zookeeper的策略:
* 5>RetryUntilElapsed
* maxElapsedTimeMs:最大重试时间
* sleepMsBetweenRetries:每次重试间隔
* 重试时间超过maxElapsedTimeMs后,就不再重试
*/
// RetryPolicy retryPolicy4 = new RetryUntilElapsed(2000, 3000);
//创建客户端
client = CuratorFrameworkFactory.builder() //builder
.connectString(zkServerPath)
.sessionTimeoutMs(10000) //session超时时间
.retryPolicy(retryPolicy) //重试策略
//namespace
.namespace("testCRUD")
.build();
/**
* CuratorFrameworkFactory工厂在创建出一个客户端CuratorFramework实例之后,实质上并没有完成会话的创建,而是需要调用
CuratorFramework的sta rt)方法来完成会话的创建。
*/
client.start();
}
/**
*
* @Description: 关闭zk客户端连接
*/
public void closeZKClient() {
if (client != null) {
this.client.close();
}
}
public static void main(String[] args) throws Exception {
// 实例化
CuratorOperator cto = new CuratorOperator();
boolean isZkCuratorStarted = cto.client.isStarted();
System.out.println("当前客户的状态:" + (isZkCuratorStarted ? "连接中" : "已关闭"));
//创建节点
String nodePath = "/dongguabai/test";
byte[] data = "abcd".getBytes();
cto.client.create()
.creatingParentContainersIfNeeded() //递归创建节点
.withMode(CreateMode.PERSISTENT) //节点模式
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) //ACL
.forPath(nodePath,data); //不指定内容,则内容为空
Thread.sleep(3000);
cto.closeZKClient();
boolean isZkCuratorStarted2 = cto.client.isStarted();
System.out.println("当前客户的状态:" + (isZkCuratorStarted2 ? "连接中" : "已关闭"));
}
}
有个要注意的地方是:
由于在ZooKeeper中规定了所有非叶子节点必须为持久节点,调用上面这个API之后,只有path参数对应的数据节点是临时节点,其父节点均为持久节点。
查询某个节点下的数据:
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.Stat;
public class CuratorOperator {
public CuratorFramework client = null;
public static final String zkServerPath = "192.168.220.135:2181,192.168.220.136:2181,192.168.220.137:2181";
/**
* 实例化zk客户端
*/
public CuratorOperator() {
/**
* 同步创建zk示例,原生api是异步的
*
* curator链接zookeeper的重试策略:
*
* 1>ExponentialBackoffRetry【推荐】
* baseSleepTimeMs:初始sleep时间(ms)
* maxRetries:最大重试次数,超过时间就不链接了
* maxSleepMs:最大重试时间(ms)
*
* 给定一个初始sleep时间base5leep丁imeMs,在这个基础上结合重试次数,通过以下公式计算出当前需要sleep的时间:
当前sleep时间=baseSleepTimeMs*Math.max(1, random.nextInt(1<<(retryCount+1)))
可以看出,随着重试次数的增加,计算出的sleep时间会越来越大。如果该sleep时间在maxSleepMs的范围之内,那么就使用该sleep时间,否则使用maxSleepMs。另外,
maxRetries参数控制了最大重试次数,以避免无限制的重试。
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);
/**
* curator链接zookeeper的策略:
* 2>RetryNTimes【推荐】
* n:重试的次数
* sleepMsBetweenRetries:每次重试间隔的时间(ms)
*/
// RetryPolicy retryPolicy = new RetryNTimes(3, 5000);
/**
* curator链接zookeeper的策略:
* 3>RetryOneTime
* sleepMsBetweenRetry:只重试一次,重试间隔的时间
*/
// RetryPolicy retryPolicy2 = new RetryOneTime(3000);
/**
* 4>
* 永远重试,不推荐使用
*/
// RetryPolicy retryPolicy3 = new RetryForever(retryIntervalMs)
/**
* curator链接zookeeper的策略:
* 5>RetryUntilElapsed
* maxElapsedTimeMs:最大重试时间
* sleepMsBetweenRetries:每次重试间隔
* 重试时间超过maxElapsedTimeMs后,就不再重试
*/
// RetryPolicy retryPolicy4 = new RetryUntilElapsed(2000, 3000);
//创建客户端
client = CuratorFrameworkFactory.builder() //builder
.connectString(zkServerPath)
.sessionTimeoutMs(10000) //session超时时间
.retryPolicy(retryPolicy) //重试策略
//namespace:
.namespace("testCRUD")
.build();
/**
* CuratorFrameworkFactory工厂在创建出一个客户端CuratorFramework实例之后,实质上并没有完成会话的创建,而是需要调用
CuratorFramework的sta rt)方法来完成会话的创建。
*/
client.start();
}
/**
*
* @Description: 关闭zk客户端连接
*/
public void closeZKClient() {
if (client != null) {
this.client.close();
}
}
public static void main(String[] args) throws Exception {
// 实例化
CuratorOperator cto = new CuratorOperator();
boolean isZkCuratorStarted = cto.client.isStarted();
System.out.println("当前客户的状态:" + (isZkCuratorStarted ? "连接中" : "已关闭"));
//创建节点
String nodePath = "/dongguabai/test";
byte[] data = "abcd".getBytes();
cto.client.create()
.creatingParentContainersIfNeeded() //递归创建节点
.withMode(CreateMode.PERSISTENT) //节点模式
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) //ACL
.forPath(nodePath,data); //不指定内容,则内容为空
//获取节点
byte[] bytes = cto.client.getData().forPath(nodePath);
System.out.println("第一次获取节点数据为:"+new String(bytes));
Stat stat = new Stat();
byte[] bytes1 = cto.client.getData().storingStatIn(stat).forPath(nodePath);
System.out.println("第二次获取节点数据为:"+new String(bytes1));
System.out.println("获取的Stat为:"+ JsonUtil.toJSON(stat));
Thread.sleep(3000);
cto.closeZKClient();
boolean isZkCuratorStarted2 = cto.client.isStarted();
System.out.println("当前客户的状态:" + (isZkCuratorStarted2 ? "连接中" : "已关闭"));
}
}
输出结果:
查询子节点:
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import java.util.List;
public class CuratorOperator {
public CuratorFramework client = null;
public static final String zkServerPath = "192.168.220.135:2181,192.168.220.136:2181,192.168.220.137:2181";
/**
* 实例化zk客户端
*/
public CuratorOperator() {
/**
* 同步创建zk示例,原生api是异步的
*
* curator链接zookeeper的重试策略:
*
* 1>ExponentialBackoffRetry【推荐】
* baseSleepTimeMs:初始sleep时间(ms)
* maxRetries:最大重试次数,超过时间就不链接了
* maxSleepMs:最大重试时间(ms)
*
* 给定一个初始sleep时间base5leep丁imeMs,在这个基础上结合重试次数,通过以下公式计算出当前需要sleep的时间:
当前sleep时间=baseSleepTimeMs*Math.max(1, random.nextInt(1<<(retryCount+1)))
可以看出,随着重试次数的增加,计算出的sleep时间会越来越大。如果该sleep时间在maxSleepMs的范围之内,那么就使用该sleep时间,否则使用maxSleepMs。另外,
maxRetries参数控制了最大重试次数,以避免无限制的重试。
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);
/**
* curator链接zookeeper的策略:
* 2>RetryNTimes【推荐】
* n:重试的次数
* sleepMsBetweenRetries:每次重试间隔的时间(ms)
*/
// RetryPolicy retryPolicy = new RetryNTimes(3, 5000);
/**
* curator链接zookeeper的策略:
* 3>RetryOneTime
* sleepMsBetweenRetry:只重试一次,重试间隔的时间
*/
// RetryPolicy retryPolicy2 = new RetryOneTime(3000);
/**
* 4>
* 永远重试,不推荐使用
*/
// RetryPolicy retryPolicy3 = new RetryForever(retryIntervalMs)
/**
* curator链接zookeeper的策略:
* 5>RetryUntilElapsed
* maxElapsedTimeMs:最大重试时间
* sleepMsBetweenRetries:每次重试间隔
* 重试时间超过maxElapsedTimeMs后,就不再重试
*/
// RetryPolicy retryPolicy4 = new RetryUntilElapsed(2000, 3000);
//创建客户端
client = CuratorFrameworkFactory.builder() //builder
.connectString(zkServerPath)
.sessionTimeoutMs(10000) //session超时时间
.retryPolicy(retryPolicy) //重试策略
//namespace:
.namespace("testCRUD")
.build();
/**
* CuratorFrameworkFactory工厂在创建出一个客户端CuratorFramework实例之后,实质上并没有完成会话的创建,而是需要调用
CuratorFramework的sta rt)方法来完成会话的创建。
*/
client.start();
}
/**
*
* @Description: 关闭zk客户端连接
*/
public void closeZKClient() {
if (client != null) {
this.client.close();
}
}
public static void main(String[] args) throws Exception {
// 实例化
CuratorOperator cto = new CuratorOperator();
boolean isZkCuratorStarted = cto.client.isStarted();
System.out.println("当前客户的状态:" + (isZkCuratorStarted ? "连接中" : "已关闭"));
String nodePath = "/dongguabai/a";
//创建节点
/* byte[] data = "abcd".getBytes();
cto.client.create()
.creatingParentContainersIfNeeded() //递归创建节点
.withMode(CreateMode.PERSISTENT) //节点模式
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) //ACL
.forPath(nodePath,data); //不指定内容,则内容为空*/
//获取节点
/* byte[] bytes = cto.client.getData().forPath(nodePath);
System.out.println("第一次获取节点数据为:"+new String(bytes));
Stat stat = new Stat();
byte[] bytes1 = cto.client.getData().storingStatIn(stat).forPath(nodePath);
System.out.println("第二次获取节点数据为:"+new String(bytes1));
System.out.println("获取的Stat为:"+ JsonUtil.toJSON(stat));
*/
//获取子节点
List list = cto.client.getChildren().forPath(nodePath);
System.out.println("开始打印子节点:");
list.forEach(result-> System.out.println(result));
System.out.println("打印结束!");
//修改节点
/* Stat stat = cto.client.setData().forPath(nodePath,"new1".getBytes());
System.out.println("第一次获取节点数据为:"+new String(cto.client.getData().forPath(nodePath)));
Stat stat1 = cto.client.setData().withVersion(stat.getVersion()).forPath(nodePath, "new2".getBytes());
System.out.println("第二次获取节点数据为:"+new String(cto.client.getData().forPath(nodePath)));*/
//删除节点
/* Stat stat = new Stat();
byte[] bytes1 = cto.client.getData().storingStatIn(stat).forPath(nodePath);
System.out.println("获取节点数据为:"+new String(bytes1));
cto.client.delete()
.guaranteed() //防止网络抖动,只要客户端会话有效,那么Curator 会在后台持续进行删除操作,直到节点删除成功
.deletingChildrenIfNeeded() //如果有子节点会删除,注意除非人为删除namespace,否则namespace不会删除
.withVersion(stat.getVersion())
.forPath(nodePath);*/
Thread.sleep(3000);
cto.closeZKClient();
boolean isZkCuratorStarted2 = cto.client.isStarted();
System.out.println("当前客户的状态:" + (isZkCuratorStarted2 ? "连接中" : "已关闭"));
}
}
修改节点:
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
public class CuratorOperator {
public CuratorFramework client = null;
public static final String zkServerPath = "192.168.220.135:2181,192.168.220.136:2181,192.168.220.137:2181";
/**
* 实例化zk客户端
*/
public CuratorOperator() {
/**
* 同步创建zk示例,原生api是异步的
*
* curator链接zookeeper的重试策略:
*
* 1>ExponentialBackoffRetry【推荐】
* baseSleepTimeMs:初始sleep时间(ms)
* maxRetries:最大重试次数,超过时间就不链接了
* maxSleepMs:最大重试时间(ms)
*
* 给定一个初始sleep时间base5leep丁imeMs,在这个基础上结合重试次数,通过以下公式计算出当前需要sleep的时间:
当前sleep时间=baseSleepTimeMs*Math.max(1, random.nextInt(1<<(retryCount+1)))
可以看出,随着重试次数的增加,计算出的sleep时间会越来越大。如果该sleep时间在maxSleepMs的范围之内,那么就使用该sleep时间,否则使用maxSleepMs。另外,
maxRetries参数控制了最大重试次数,以避免无限制的重试。
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);
/**
* curator链接zookeeper的策略:
* 2>RetryNTimes【推荐】
* n:重试的次数
* sleepMsBetweenRetries:每次重试间隔的时间(ms)
*/
// RetryPolicy retryPolicy = new RetryNTimes(3, 5000);
/**
* curator链接zookeeper的策略:
* 3>RetryOneTime
* sleepMsBetweenRetry:只重试一次,重试间隔的时间
*/
// RetryPolicy retryPolicy2 = new RetryOneTime(3000);
/**
* 4>
* 永远重试,不推荐使用
*/
// RetryPolicy retryPolicy3 = new RetryForever(retryIntervalMs)
/**
* curator链接zookeeper的策略:
* 5>RetryUntilElapsed
* maxElapsedTimeMs:最大重试时间
* sleepMsBetweenRetries:每次重试间隔
* 重试时间超过maxElapsedTimeMs后,就不再重试
*/
// RetryPolicy retryPolicy4 = new RetryUntilElapsed(2000, 3000);
//创建客户端
client = CuratorFrameworkFactory.builder() //builder
.connectString(zkServerPath)
.sessionTimeoutMs(10000) //session超时时间
.retryPolicy(retryPolicy) //重试策略
//namespace:
.namespace("testCRUD")
.build();
/**
* CuratorFrameworkFactory工厂在创建出一个客户端CuratorFramework实例之后,实质上并没有完成会话的创建,而是需要调用
CuratorFramework的sta rt)方法来完成会话的创建。
*/
client.start();
}
/**
*
* @Description: 关闭zk客户端连接
*/
public void closeZKClient() {
if (client != null) {
this.client.close();
}
}
public static void main(String[] args) throws Exception {
// 实例化
CuratorOperator cto = new CuratorOperator();
boolean isZkCuratorStarted = cto.client.isStarted();
System.out.println("当前客户的状态:" + (isZkCuratorStarted ? "连接中" : "已关闭"));
String nodePath = "/dongguabai/test";
//创建节点
/* byte[] data = "abcd".getBytes();
cto.client.create()
.creatingParentContainersIfNeeded() //递归创建节点
.withMode(CreateMode.PERSISTENT) //节点模式
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) //ACL
.forPath(nodePath,data); //不指定内容,则内容为空*/
//获取节点
/* byte[] bytes = cto.client.getData().forPath(nodePath);
System.out.println("第一次获取节点数据为:"+new String(bytes));
Stat stat = new Stat();
byte[] bytes1 = cto.client.getData().storingStatIn(stat).forPath(nodePath);
System.out.println("第二次获取节点数据为:"+new String(bytes1));
System.out.println("获取的Stat为:"+ JsonUtil.toJSON(stat));*/
//修改节点
Stat stat = cto.client.setData().forPath(nodePath,"new1".getBytes());
System.out.println("第一次获取节点数据为:"+new String(cto.client.getData().forPath(nodePath)));
Stat stat1 = cto.client.setData().withVersion(stat.getVersion()).forPath(nodePath, "new2".getBytes());
System.out.println("第二次获取节点数据为:"+new String(cto.client.getData().forPath(nodePath)));
Thread.sleep(3000);
cto.closeZKClient();
boolean isZkCuratorStarted2 = cto.client.isStarted();
System.out.println("当前客户的状态:" + (isZkCuratorStarted2 ? "连接中" : "已关闭"));
}
}
输出结果:
删除节点:
执行程序之前:
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
public class CuratorOperator {
public CuratorFramework client = null;
public static final String zkServerPath = "192.168.220.135:2181,192.168.220.136:2181,192.168.220.137:2181";
/**
* 实例化zk客户端
*/
public CuratorOperator() {
/**
* 同步创建zk示例,原生api是异步的
*
* curator链接zookeeper的重试策略:
*
* 1>ExponentialBackoffRetry【推荐】
* baseSleepTimeMs:初始sleep时间(ms)
* maxRetries:最大重试次数,超过时间就不链接了
* maxSleepMs:最大重试时间(ms)
*
* 给定一个初始sleep时间base5leep丁imeMs,在这个基础上结合重试次数,通过以下公式计算出当前需要sleep的时间:
当前sleep时间=baseSleepTimeMs*Math.max(1, random.nextInt(1<<(retryCount+1)))
可以看出,随着重试次数的增加,计算出的sleep时间会越来越大。如果该sleep时间在maxSleepMs的范围之内,那么就使用该sleep时间,否则使用maxSleepMs。另外,
maxRetries参数控制了最大重试次数,以避免无限制的重试。
*/
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 5);
/**
* curator链接zookeeper的策略:
* 2>RetryNTimes【推荐】
* n:重试的次数
* sleepMsBetweenRetries:每次重试间隔的时间(ms)
*/
// RetryPolicy retryPolicy = new RetryNTimes(3, 5000);
/**
* curator链接zookeeper的策略:
* 3>RetryOneTime
* sleepMsBetweenRetry:只重试一次,重试间隔的时间
*/
// RetryPolicy retryPolicy2 = new RetryOneTime(3000);
/**
* 4>
* 永远重试,不推荐使用
*/
// RetryPolicy retryPolicy3 = new RetryForever(retryIntervalMs)
/**
* curator链接zookeeper的策略:
* 5>RetryUntilElapsed
* maxElapsedTimeMs:最大重试时间
* sleepMsBetweenRetries:每次重试间隔
* 重试时间超过maxElapsedTimeMs后,就不再重试
*/
// RetryPolicy retryPolicy4 = new RetryUntilElapsed(2000, 3000);
//创建客户端
client = CuratorFrameworkFactory.builder() //builder
.connectString(zkServerPath)
.sessionTimeoutMs(10000) //session超时时间
.retryPolicy(retryPolicy) //重试策略
//namespace:
.namespace("testCRUD")
.build();
/**
* CuratorFrameworkFactory工厂在创建出一个客户端CuratorFramework实例之后,实质上并没有完成会话的创建,而是需要调用
CuratorFramework的sta rt)方法来完成会话的创建。
*/
client.start();
}
/**
*
* @Description: 关闭zk客户端连接
*/
public void closeZKClient() {
if (client != null) {
this.client.close();
}
}
public static void main(String[] args) throws Exception {
// 实例化
CuratorOperator cto = new CuratorOperator();
boolean isZkCuratorStarted = cto.client.isStarted();
System.out.println("当前客户的状态:" + (isZkCuratorStarted ? "连接中" : "已关闭"));
String nodePath = "/dongguabai/test";
//创建节点
/* byte[] data = "abcd".getBytes();
cto.client.create()
.creatingParentContainersIfNeeded() //递归创建节点
.withMode(CreateMode.PERSISTENT) //节点模式
.withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE) //ACL
.forPath(nodePath,data); //不指定内容,则内容为空*/
//获取节点
/* byte[] bytes = cto.client.getData().forPath(nodePath);
System.out.println("第一次获取节点数据为:"+new String(bytes));
Stat stat = new Stat();
byte[] bytes1 = cto.client.getData().storingStatIn(stat).forPath(nodePath);
System.out.println("第二次获取节点数据为:"+new String(bytes1));
System.out.println("获取的Stat为:"+ JsonUtil.toJSON(stat));*/
//修改节点
/* Stat stat = cto.client.setData().forPath(nodePath,"new1".getBytes());
System.out.println("第一次获取节点数据为:"+new String(cto.client.getData().forPath(nodePath)));
Stat stat1 = cto.client.setData().withVersion(stat.getVersion()).forPath(nodePath, "new2".getBytes());
System.out.println("第二次获取节点数据为:"+new String(cto.client.getData().forPath(nodePath)));*/
//删除节点
Stat stat = new Stat();
byte[] bytes1 = cto.client.getData().storingStatIn(stat).forPath(nodePath);
System.out.println("获取节点数据为:"+new String(bytes1));
cto.client.delete()
.guaranteed() //防止网络抖动,只要客户端会话有效,那么Curator 会在后台持续进行删除操作,直到节点删除成功
.deletingChildrenIfNeeded() //如果有子节点会删除,注意除非人为删除namespace,否则namespace不会删除
.withVersion(stat.getVersion())
.forPath(nodePath);
Thread.sleep(3000);
cto.closeZKClient();
boolean isZkCuratorStarted2 = cto.client.isStarted();
System.out.println("当前客户的状态:" + (isZkCuratorStarted2 ? "连接中" : "已关闭"));
}
}
执行结果:
判断节点是否存在:
其他相关资料:
https://blog.csdn.net/en_joker/article/details/78778917
https://www.cnblogs.com/LiZhiW/p/4926385.html?utm_source=tuicool&utm_medium=referral