Java Api操作Zookeeper

连接Zookeeper

重启创建zk1容器,将容器2181端口映射到本机

docker rm -f zk1
docker run -itd --name zk1 -p 2181:2181 -v ~/zkcluster/zk1/zoo.cfg:/conf/zoo.cfg -v ~/zkcluster/zk1/data:/data --network zknet --network-alias zk1 zookeeper

java端

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.6.1</version>
</dependency>

在连接状态为 Event.KeeperState.SyncConnected 的时候表示连接成功,所以需要阻塞当前线程,当获取到Zookeeper实例时再释放。这里用 CountDownLatch 对主线程阻塞,在 process 方法中释放阻塞

public class ZkDemo1 {
    public static void main(String[] args) {
        try {
            CountDownLatch countDownLatch = new CountDownLatch(1);
            ZooKeeper zooKeeper = new ZooKeeper("192.168.159.129:2181", 5000, new Watcher() {
                @Override
                public void process(WatchedEvent watchedEvent) {
                    if (Event.KeeperState.SyncConnected == watchedEvent.getState()) {
                        System.out.println("连接创建成功..");
                        countDownLatch.countDown();
                    }
                }
            });
            countDownLatch.await();
            // 在这之后可以对zookeeper进行操作
            // ...
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

创建节点

在创建节点时,可以自定义Acl,或者用已经预定义好的Acl

用默认的Acl创建节点,就像shell窗口 create /zknode 一样,默认的权限是 world:anyone:cdrwa

zooKeeper.create("/demo", "哈哈哈嗝".getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);

这行代码创建了 /demo 节点,值是 哈哈哈嗝ZooDefs.Ids.OPEN_ACL_UNSAFE 看源码可知是 world:anyone:cdrwaCreateMode.PERSISTENT 表示创建的是一个临时节点

追踪源码可以发现,create 方法传入的Acl只是一个 ArrayList<ACL>ACL 对象由 ZooDefs.PermsId 构成。

image20200630140522562.png

ZooDefs.Perms.ALL 表示 cdrwa 权限,只是把前面几种权限 | 了一下,可以发现,可以用同样的方式构建自定义权限,比如 ZooDefs.Perms.READ | ZooDefs.Perms.ADMIN 代表 ra 权限。

简单的把5种权限看成5位表示的二进制数 11111 就是 ZooDefs.Perms.ALL,也就是31。10001 = 17 代表 ra 权限。规律也挺简单的。

来看个自定义权限的例子:

try {
    ArrayList<ACL> acls = new ArrayList<>();
    acls.add(new ACL(ZooDefs.Perms.READ | ZooDefs.Perms.ADMIN, ZooDefs.Ids.ANYONE_ID_UNSAFE));
    zooKeeper.create("/demo", "哈哈哈嗝".getBytes(StandardCharsets.UTF_8), acls, CreateMode.PERSISTENT);
} catch (Exception e) {
    e.printStackTrace();
}

创建了 /demo 节点,值为 哈哈哈嗝。权限是 ra

查询节点

传入了三个参数

  • path:节点路径
  • watcher:监听器
  • stat:元属性
try {
    CountDownLatch countDownLatch = new CountDownLatch(1);
    Stat stat = new Stat();
    byte[] data = zooKeeper.getData("/demo", event -> {
        // 打印事件类型
        System.out.println("----------watch---------");
        System.out.println(event.getType());
        
        countDownLatch.countDown();
    }, stat);
    // 打印数据
    System.out.println("----------data-----------");
    System.out.println(new String(data, StandardCharsets.UTF_8));
    // 获取元属性
    System.out.println("----------stat-----------");
    System.out.println(stat.getDataLength());
    System.out.println(stat.getVersion());
    
    countDownLatch.await();
} catch (Exception e) {
    e.printStackTrace();
}

打印了 /demo 的数据和元属性,并且传入一个监听器,一直到事件触发时程序才结束

image20200630183315187.png

修改 /demo 节点

image20200630183323338.png

触发了监听器事件

image20200630183345520.png

当然不需要监听和查看元属性,也可以设置为null

byte[] data = zooKeeper.getData("/demo", null, null);

修改节点数据

传入3个参数:

  • path:节点路径
  • data:节点新数据
  • version:版本号,如果传 -1,则视为不根据版本号修改
zookeeper.setData("/demo", "咯咯嗝".getBytes(StandardCharsets.UTF_8), -1);

删除节点

传入2个参数

  • path:节点路径
  • version:版本号
zooKeeper.delete("/zknode", -1);

如果 /zknode 还有子节点,删除失败。如果需要删除由子节点的节点,需要自己实现递归删除逻辑

查看所有子节点

名字不是以 / 开头的,如果需要查看子节点的子节点,需要在头部加上 /

List<String> children = zooKeeper.getChildren(path, false);

设置ACL

zooKeeper.setACL("/demo", ZooDefs.Ids.OPEN_ACL_UNSAFE, -1);
# Zookeeper 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×