- 引入Zookeeper
<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.1</version>
</dependency>
- 创建节点
/**
3. curator
4. 创建节点
5. 作者:负差生
6. 时间:2021年6月3日13:36:46
*/
public class CreateNodeDemo {
/** 重试策略:重试间隔时间为1000ms; 最多重试3次; */
private static RetryPolicy retryPolicy = new RetryNTimes(3, 1000);
private static ZooKeeper zooKeeper;
public static void main(String[] args) throws Exception {
//建立链接
//connectString:链接地址
//sessionTimeoutMs:会话超时时间
//connectTimeoutMs:链接超时间、
//重试策略
CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("localhost:2181", 5000,
5000, retryPolicy);
//建立链接
curatorFramework.start();
// 其中creatingParentsIfNeeded()的作用为:如果要创建的节点的父节点不存在,那么会先创建父节点,再创建该节点
String newNode = curatorFramework
.create()
.creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT)
.forPath("/a_node/a_1", "".getBytes());
System.out.println("新创建的节点是:" + newNode);
}
}
测试
- 删除节点
**
8. curator
9. 创建节点
10. 作者:负差生
11. 时间:2021年6月3日13:36:46
*/
public class DeleteNodeDemo {
/** 重试策略:重试间隔时间为1000ms; 最多重试3次; */
private static RetryPolicy retryPolicy = new RetryNTimes(3, 1000);
public static void main(String[] args) throws Exception {
CuratorFramework curator = CuratorFrameworkFactory.newClient("localhost:2181", 5000, 5000, retryPolicy);
curator.start();
// 删除(无子节点的)节点
//client.delete().forPath("/a_node");
// 删除指定版本的(无子节点的)节点
//client.delete().withVersion(4).forPath("/a_node");
// 删除节点(如果有子节点,也一并删除)
curator.delete().deletingChildrenIfNeeded().forPath("/a_node");
// 删除指定版本的节点(如果有子节点,也一并删除)
//client.delete().deletingChildrenIfNeeded().withVersion(4).forPath("/a_node");
// 只要Session有效,那么就会对指定节点进行持续删除,直到删除成功; 这是一种保障机制
//client.delete().guaranteed().deletingChildrenIfNeeded().withVersion(4).forPath("/a_node");
}
}
- . 获取节点数据
// 获取节点的数据的同时,并将节点状态信息放入传入的stat实例中
Stat stat = new Stat();
//获取数据信息
byte[] data = client.getData().storingStatIn(stat).forPath("/");
//转为string
System.out.println("节点“/”的数据内容为:" + new String(data));
System.out.println("节点“/”的stat状态信息为:" + stat);
- 重置节点
public class SetDemo {
/** 重试策略:重试间隔时间为1000ms; 最多重试3次; */
private static RetryPolicy retryPolicy = new RetryNTimes(3, 1000);
public static void main(String[] args) throws Exception {
CuratorFramework curator = CuratorFrameworkFactory.newClient("localhost:2021", 5000, 5000,
retryPolicy);
curator.start();
// 设置节点数据
// client.setData().forPath("/", "我是修改后的节点数据内容".getBytes());
// 先获取到节点的状态
Stat statOne = new Stat();
curator.getData().storingStatIn(statOne).forPath("/");
System.out.println("修改节点“/”的数据后,数据版本为:" + statOne.getVersion());
// 设置节点数据(校验版本信息)
Stat statTwo = curator.setData().withVersion(statOne.getVersion()).forPath("/", "我是修改后的节点数据内容".getBytes());
System.out.println("修改节点“/”的数据后,数据版本为:" + statTwo.getVersion());
}
}
- 判断节点存在
Stat stat = client.checkExists().forPath("/");
System.out.println(stat == null ? "节点不存在!" : "节点存在!");
- 获取子节点
List<String> children = client.getChildren().forPath("/");
System.out.println("节点“/”的子节点集合:" + children);
- 设置权限
// ID白名单模式,给ip为localhost的客户端分配所有权限
ACL aclIdOne = new ACL(ZooDefs.Perms.ALL, new Id("ip", "localhost"));
// ID白名单模式,给ip为10.8.109.76的客户端分配 读 的权限
ACL aclIdTwo = new ACL(ZooDefs.Perms.READ, new Id("ip", "10.8.109.76"));
// ID白名单模式,给ip为localhost的客户端分配 读和写 的权限
ACL aclIdThree = new ACL(ZooDefs.Perms.READ | ZooDefs.Perms.WRITE, new Id("ip", "10.8.109.44"));
// 用户名密码模式,设置userOne用户,有所有权限
ACL aclDigestOne = new ACL(ZooDefs.Perms.ALL, new Id("digest", DigestAuthenticationProvider.generateDigest("userOne:123")));
// 用户名密码模式,设置userTwo用户,有 读 权限
ACL aclDigestTwo = new ACL(ZooDefs.Perms.READ, new Id("digest", DigestAuthenticationProvider.generateDigest("userTwo:123")));
// 用户名密码模式,设置userThree用户,有 读和写 权限
ACL aclDigestThree = new ACL(ZooDefs.Perms.READ | ZooDefs.Perms.WRITE, new Id("digest", DigestAuthenticationProvider.generateDigest("userThree:123")));
List<ACL> acls = new ArrayList<>(8);
acls.add(aclIdOne);
acls.add(aclIdTwo);
acls.add(aclIdThree);
acls.add(aclDigestOne);
acls.add(aclDigestTwo);
acls.add(aclDigestThree);
// 其中creatingParentsIfNeeded()的作用为:如果要创建的节点的父节点不存在,那么会先创建父节点,再创建该节点
String newNode = client
.create()
.creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT)
.withACL(acls)
.forPath("/auth_node", "".getBytes());
System.out.println("新创建的节点是:" + newNode);
- 添加监听
//client客户端
//监听节点位置
//最后一个参数为true,表示出节点内容外还监听缓存内容
final PathChildrenCache cache = new PathChildrenCache(client,"/", true);
// 开始监听
//如果路径下存在原始节点,则设置参数,否则会将元节点当新节点发送event
cache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE);
// 当目标节点的子节点被创建、子节点被删除、子节点数据内容发生变化等时,会触发监听方法
cache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
System.out.println("线程" + Thread.currentThread().getName() + "说,进入监听方法了!");
byte[] data;
switch (event.getType()){
case CHILD_ADDED :
System.out.println("新增子节点!");
System.out.println("子节点path为:" + event.getData().getPath());
System.out.println("子节点Stat为:" + event.getData().getStat());
data = event.getData().getData();
System.out.println("子节点数据内容为:" + (data == null ? null : new String(data)));
break;
case CHILD_REMOVED :
System.out.println("删除子节点!");
System.out.println("子节点path为:" + event.getData().getPath());
System.out.println("子节点Stat为:" + event.getData().getStat());
data = event.getData().getData();
System.out.println("子节点数据内容为:" + (data == null ? null : new String(data)));
break;
case CHILD_UPDATED :
System.out.println("修改子节点数据内容!");
System.out.println("子节点path为:" + event.getData().getPath());
System.out.println("子节点Stat为:" + event.getData().getStat());
data = event.getData().getData();
System.out.println("子节点数据内容为:" + (data == null ? null : new String(data)));
break;
default :
System.out.println("default!");
}
}
});
11. 异步调用示例(以创建节点数据示例)
public class AsyncDemo {
/** 重试策略:重试间隔时间为1000ms; 最多重试3次; */
private static RetryPolicy retryPolicy = new RetryNTimes(3, 1000);
/**
* 实现异步调用接口
*/
private static class MyBackgroundCallback implements BackgroundCallback {
@Override
public void processResult(CuratorFramework client, CuratorEvent event) throws Exception {
System.out.println("进入回调方法了!执行此方法的线程是:" + Thread.currentThread().getName());
StringBuilder sb = new StringBuilder(64);
sb.append("操作事件类型CuratorEventType为:").append(event.getType()).append("\n");
sb.append("ACL为:").append(event.getACLList()).append("\n");
sb.append("子节点集合为:").append(event.getChildren()).append("\n");
sb.append("操作时传入的上下文数据:").append(event.getContext()).append("\n");
sb.append("所操作节点(操作进行前)为:").append(event.getPath()).append("\n");
byte[] data = event.getData();
sb.append("所操作节点数据内容为:").append(data == null ? null : new String(data)).append("\n");
// 当节点类型为 有序节点时,path与name不一致
sb.append("所操作节点(操作进行后)为:").append(event.getName()).append("\n");
// 操作成功的结果码为0
sb.append("操作结果码为:").append(event.getResultCode()).append("\n");
sb.append("所操作节点stat为:").append(event.getStat()).append("\n");
sb.append("WatchedEvent为:").append(event.getWatchedEvent());
System.out.println(sb.toString());
}
}
public static void main(String[] args) throws Exception {
CuratorFramework client = CuratorFrameworkFactory.newClient("localhost:2181",5000,
5000, retryPolicy);
// 启动客户端
client.start();
/*
异步创建节点
注:inBackground有多个重载方法;根据实际情况选择适合的即可
注:执行回调函数的是一个单独的线程;如果同一时刻回调函数较多的话,我们就可以考虑引入线程池(不引入的话,频繁的创建销毁线程会比较耗性能)
inBackground(BackgroundCallback callback, Object context, Executor executor);
.withMode(CreateMode.PERSISTENT_SEQUENTIAL)设置是否是带有自增ID
*/
client.create()
.withMode(CreateMode.PERSISTENT_SEQUENTIAL)
.inBackground(new MyBackgroundCallback(), "我是上下文Object数据")
.forPath("/abc", "异步创建节点".getBytes());
// 为了看见控制台输出,我们不能让main线程死得太早
TimeUnit.MILLISECONDS.sleep(10000);
}
}