之前写过命令行的使用,如果没看过或者没记住的可以参考一下哈:
zookeeper系列之命令行讲解_阿小冰的博客-CSDN博客zookeeper系列之命令行讲解https://blog.csdn.net/qq_38377525/article/details/123326056咱们都是做JAVA开发的,所以对于代码集成ZK的API也是必不可少的,所以这里做一次API的使用记录
API介绍
zookeeper为多种语言都提供了API接口,那这里咱们主要讲一下JAVA的API使用,zookeeper的API主要是有五个包,分别是:
1、org.apache.zookeeper:最主要的一个类,我们要使用zk服务,就必须要先创建一个zk的实例,就是要创建这个ZooKeeper类的实例
2、org.apache.zookeeper.data
3、org.apache.zookeeper.server
4、org.apache.zookeeper.server.quorum
5、org.apache.zookeeper.server.upgrade
JAVA代码调用API
1、导入依赖
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.14</version>
</dependency>
2、创建会话
public class CreateSession implements Watcher {
//为了不让main方法直接结束
private static CountDownLatch countDownLatch = new CountDownLatch(1);
public static void main(String[] args) throws IOException, InterruptedException {
ZooKeeper zooKeeper = new ZooKeeper(
"127.0.0.1:2181", //链接地址,IP:port
5000,//会话超时时间ms
new CreateSession());//监听器,当特定事件触发监听时,zk会通过watcher通知到客户端
System.out.println("zk当前状态是:" + zooKeeper.getState());
//线程等待
countDownLatch.await();
//打印,证明会话创建成功
System.out.println("session created");
}
/**
* @Description: 负责处理来自zk服务端的监听器通知,在收到服务端发送过来的SyncConnected事件之后,
* 解除主程序在CountDownLatch上的阻塞,说明这个时候会话已结束
*/
@Override
public void process(WatchedEvent watchedEvent) {
//当创建链接后,服务端发送给客户端一个SunvConnected事件
if(watchedEvent.getState()==Event.KeeperState.SyncConnected){
//销毁线程
countDownLatch.countDown();
}
}
}
执行main方法,观察控制台打印:
说明会话已建立
3、创建节点
public class CreateNode implements Watcher {
//为了不让main方法直接结束
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static ZooKeeper zooKeeper;
public static void main(String[] args) throws IOException, InterruptedException {
zooKeeper = new ZooKeeper(
"127.0.0.1:2181", //链接地址,IP:port
5000,//会话超时事件ms
new CreateNode());//监听器,当特定事件出发监听时,zk会通过watcher通知到客户端
System.out.println("zk当前状态是:" + zooKeeper.getState());
//线程等待
countDownLatch.await();
//打印,证明会话创建成功
System.out.println("znode created");
}
/**
* @Description: 负责处理来自zk服务端的监听器通知,在收到服务端发送过来的SyncConnected事件之后,
* 解除主程序在CountDownLatch上的阻塞,说明这个时候会话已结束
*/
@Override
public void process(WatchedEvent watchedEvent) {
//创建节点
try {
createNode();
}catch (Exception e) {
e.printStackTrace();
}
//当创建链接后,服务端发送给客户端一个SunvConnected事件
if (watchedEvent.getState() == Event.KeeperState.SyncConnected) {
//销毁线程
countDownLatch.countDown();
}
}
private void createNode() throws Exception{
/* public String create(
String path,节点创建路径
byte[] data, 节点数据,是个byte类型
List<ACL> acl, 节点创建的权限信息,他有四个值
ANYONE_ID_UNSAFE:表示任何人
AUTH_IDS:仅仅用于设置ACL
OPEN_ACL_UNSAFE:一个完全开放的ACL,还是比较常用的
CREATOR_ALL_ACL:授予创建者身份验证ID的所有权限
CreateMode createMode):创建节点的类型
PERSISTENT:持久节点
PERSISTENT_SEQUENTIAL:持久顺序节点
EPHEMERAL:临时节点
EPHEMERAL_SEQUENTIAL:临时顺序节点
*/
String node_PERSISTENT = zooKeeper.create("/api_persistent", "持久节点的内容".getBytes("utf-8"), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
String node_PERSISTENT_SEQUENTIAL =
zooKeeper.create("/api_persistent_sequential", "持久顺序节点的内容".getBytes("utf-8"),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL);
String node_EPERSISTENT = zooKeeper.create("/api_ephemeral", "临时节点的内容".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
System.out.println("创建的持久节点是:" + node_PERSISTENT);
System.out.println("创建的持久顺序节点是:" + node_PERSISTENT_SEQUENTIAL);
System.out.println("创建的临时节点是:" + node_EPERSISTENT);
}
}
查看可视化工具是否真的创建成功:
三个api开头的节点,说明创建成功
4、获取节点数据
public class GetNode implements Watcher {
//为了不让main方法直接结束
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static ZooKeeper zooKeeper;
public static void main(String[] args) throws IOException, InterruptedException {
zooKeeper = new ZooKeeper(
"127.0.0.1:2181", //链接地址,IP:port
5000,//会话超时事件ms
new GetNode());//监听器,当特定事件出发监听时,zk会通过watcher通知到客户端
//线程等待
countDownLatch.await();
System.out.println("get success");
}
/**
* @Description: 负责处理来自zk服务端的监听器通知,在收到服务端发送过来的SyncConnected事件之后,
* 解除主程序在CountDownLatch上的阻塞,说明这个时候会话已结束
*/
@Override
public void process(WatchedEvent watchedEvent) {
//⼦节点列表发⽣变化时,服务器会发出NodeChildrenChanged通知,但不会把变化情况告诉给客户端
// 需要客户端⾃⾏获取,且通知是⼀次性的,需反复注册监听
if(watchedEvent.getType() ==Event.EventType.NodeChildrenChanged){
//再次获取节点数据
try {
List<String> children =
zooKeeper.getChildren(watchedEvent.getPath(), true);
System.out.println(children);
} catch (Exception e) {
e.printStackTrace();
}
}
if(watchedEvent.getState() == Event.KeeperState.SyncConnected){
try {
//调用获取单个节点数据方法
getNodeDate();
//获取子节点信息
getChildrens();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void getNodeDate() throws Exception {
byte[] data = zooKeeper.getData("/api_persistent", true, null);
System.out.println(new String(data, "utf-8"));
}
private static void getChildrens() throws KeeperException, InterruptedException {
/* zooKeeper.getChildren(
path, 路径
watch);是否要启动监听,当⼦节点列表发⽣变化,会触发监听
*/
List<String> children = zooKeeper.getChildren("/api_persistent", true);
System.out.println(children);
}
}
查看日志:
说明成功,下面的[]是因为当前节点下无子节点信息,所以返回的[]
5、修改节点数据
public class UpdateNode implements Watcher {
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static ZooKeeper zooKeeper;
public static void main(String[] args) throws Exception {
zooKeeper = new ZooKeeper("127.0.0.1:2181", 5000, new UpdateNode());
countDownLatch.await();
}
public void process(WatchedEvent watchedEvent) {
try {
updateNodeSync();
} catch (Exception e) {
e.printStackTrace();
}
}
private void updateNodeSync() throws Exception {
/*
zooKeeper.setData(path,路径
data,要修改的内容 byte[]
version);表示对最新版本的数据进⾏修改
*/
byte[] data = zooKeeper.getData("/api_persistent", false, null);
System.out.println("修改前的值:" + new String(data));
//修改 stat:状态信息对象 -1:最新版本
Stat stat = zooKeeper.setData("/api_persistent", "客户端修改内容".getBytes(), -1);
byte[] data2 = zooKeeper.getData("/api_persistent", false, null);
System.out.println("修改后的值:" + new String(data2));
}
}
观察日志打印:
6、删除节点数据
删除之前看一下Znode Tree:
那我们来删除一下zk-create-s0000000002,代码如下:
public class DeleteNode implements Watcher {
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static ZooKeeper zooKeeper;
public static void main(String[] args) throws Exception {
zooKeeper = new ZooKeeper("127.0.0.1:2181", 5000, new DeleteNode());
countDownLatch.await();
}
public void process(WatchedEvent watchedEvent) {
//当连接创建了,服务端发送给客户端SyncConnected事件
try {
deleteNodeSync();
} catch (Exception e) {
e.printStackTrace();
}
}
private void deleteNodeSync() throws KeeperException, InterruptedException {
/*
zooKeeper.exists(path,watch) :判断节点是否存在
zookeeper.delete(path,version) : 删除节点
*/
Stat exists = zooKeeper.exists("/zk-create-s0000000002", false);
System.out.println(exists == null ? "该节点不存在" : "该节点存在");
zooKeeper.delete("/zk-create-s0000000002", -1);
Stat exists2 = zooKeeper.exists("/zk-create-s0000000002", false);
System.out.println(exists2 == null ? "该节点不存在" : "该节点存在");
}
}
查看日志打印:
再查看一下可视化工具的内容:
刚才的zk-create-s0000000002已经被删除了
以上案例是直接使用ZooKeeper源码工具类直接操作,其实网上有很多开源的zk客户端工具类,帮我们封装了上面案例中的API,节省了比上面代码还要多的代码,用起来也很方便,大多数情况开发的时候都会用封装类,也就是ZkClient,这里就不做陈述了,只不过建议是先了解底层提供的API然后再去使用封装工具类,这样也不至于只会用不知底的情况