Zookeeper开源客户端curator

目录

一、curator简介

二、curator使用

三、curator重连策略

四、curator新增节点

五、curator更新节点

六、curator查看节点

七、curator查看子节点

八、curator删除节点

九、总结


一、curator简介

curator是Netflix公司开源的一个zookeeper客户端,curator框架在zookeeper原生API接口上进行了包装,解决了很多zooKeeper客户端非常底层的细节开发。提供zooKeeper各种应用场景(比如:分布式锁服务、集群领导选举、共享计数器、缓存机制、分布式队列等)的抽象封装,实现了Fluent风格的API接口,curator是最好用,最流行的zookeeper的客户端。

原生zookeeperAPI的不足:

  1. 连接对象异步创建,需要开发人员自行编码等待;
  2. 连接没有自动重连超时机制;
  3. watcher一次注册只生效一次;
  4. 不支持递归创建树形节点;

curator特点:

  1. 解决session会话超时重连;
  2. watcher监听机制反复注册;
  3. 简化开发API;
  4. 遵循Fluent风格的API;
  5. 提供了分布式锁服务、共享计数器、缓存机制等机制;

二、curator使用

如果需要使用curator框架的话,只需要我们在项目的依赖文件中加入curator的依赖即可,如下:

<dependency>
  <groupId>org.apache.curator</groupId>
  <artifactId>curator-framework</artifactId>
  <version>2.6.0</version>
  <type>jar</type>
  <exclusions>
      <exclusion>
          <groupId>org.apache.zookeeper</groupId>
          <artifactId>zookeeper</artifactId>
      </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.apache.zookeeper</groupId>
  <artifactId>zookeeper</artifactId>
  <version>3.4.10</version>
  <type>jar</type>
</dependency>
<dependency>
  <groupId>org.apache.curator</groupId>
  <artifactId>curator-recipes</artifactId>
  <version>2.6.0</version>
  <type>jar</type>
</dependency>

三、curator重连策略

在zookeeper原生API中,当客户端与服务端断开连接后,并不会进行自动重连,curator框架对其封装了一下,允许客户端与服务器端断开连接后,自动根据配置的重连策略进行重连。

一般有下面四种重连策略,都是基于RetryPolicy接口实现的:

public interface RetryPolicy{
    public boolean  allowRetry(int retryCount, long elapsedTimeMs, RetrySleeper sleeper);
}
  • RetryOneTime:只重连1次;
/**
 * RetryOneTime: 5秒后重连一次,只重连1次.
 */
RetryPolicy retryOneTime = new RetryOneTime(5000);
  • RetryNTimes:重连n次;
/**
 * RetryNTimes: 每5秒重连一次,重连5次.
 */
RetryPolicy retryNTimes = new RetryNTimes(5, 5000);
  • ExponentialBackoffRetry:随着重试次数的增加,每一次重试的时间间隔越来越大;
/**
 * BoundedExponentialBackoffRetry: 随着重试次数的增加,每一次重试的时间间隔越来越大.
 * 每一次重试时间: baseSleepTimeMs * Math.max(1, random.nextInt(1 << (retryCount + 1)))
 */
RetryPolicy exponentialBackoffRetry = new ExponentialBackoffRetry(1000, 3);
  • RetryUntilElapsed:每n秒重连一次,总等待时间超过m秒后停止重连;
/**
 * RetryUntilElapsed: 每5秒重连一次,总等待时间超过10秒后停止重连.
 */
RetryPolicy retryUntilElapsed = new RetryUntilElapsed(10000, 5000);

四、curator新增节点

下面分四种情况分别介绍如何使用curator客户端API去操作zookeeper创建节点。

基础代码如下:

package com.wsh.zookeeper.zookeeperapidemo.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Id;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class CuratorCreateNodeDemo {

    private static final Logger logger = LoggerFactory.getLogger(CuratorCreateNodeDemo.class);
    private static final String ZOOKEEPER_SERVER_ADDRESS = "192.168.179.128:2181,192.168.179.129:2181,192.168.179.133:2181";

    /**
     * Curator对象
     */
    private static CuratorFramework curatorFramework;

    static {
        //初始化curator对象
        curatorFramework = CuratorFrameworkFactory
                .builder()
                //会话超时时间
                .sessionTimeoutMs(5000)
                //服务器集群地址
                .connectString(ZOOKEEPER_SERVER_ADDRESS)
                //重试策略
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间,如果制定了命名空间,那么创建的节点的根目录就是/create
                .namespace("create")
                .build();
        //开启客户端
        curatorFramework.start();
    }

    /**
     * 1.创建一个节点
     */
    public void create01() throws Exception {
        curatorFramework.create()
                //节点类型:持久化节点
                .withMode(CreateMode.PERSISTENT)
                //权限列表  crdwa
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                //节点路径
                .forPath("/node1", "node1".getBytes());
    }

    /**
     * 2. 自定义权限列表
     */
    public void create02() throws Exception {
        List<ACL> aclArrayList = new ArrayList<ACL>();
        Id id = new Id("ip", "192.168.179.133");
        aclArrayList.add(new ACL(ZooDefs.Perms.ALL, id));
        curatorFramework.create()
                //节点类型:持久化节点
                .withMode(CreateMode.PERSISTENT)
                //权限列表
                .withACL(aclArrayList)
                //节点路径
                .forPath("/node2", "node2".getBytes());
    }

    /**
     * 3. 递归创建节点
     */
    public void create03() throws Exception {
        curatorFramework.create()
                //当父节点不存在时,自动创建父节点
                .creatingParentsIfNeeded()
                //节点类型:持久化节点
                .withMode(CreateMode.PERSISTENT)
                //权限列表
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                //节点路径
                .forPath("/node3/node31", "node31".getBytes());
    }

    /**
     * 4. 异步方式创建节点
     */
    public void create04() throws Exception {
        curatorFramework.create()
                //节点类型:持久化节点
                .withMode(CreateMode.PERSISTENT)
                //权限列表
                .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)
                //异步方式创建节点,匿名内部类实现BackgroundCallback的processResult方法
                .inBackground(new BackgroundCallback() {
                    @Override
                    public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                        logger.info("节点路径:" + curatorEvent.getPath());
                        logger.info("事件类型:" + curatorEvent.getType());
                    }
                })
                //节点路径
                .forPath("/node4", "node4".getBytes());
        TimeUnit.SECONDS.sleep(5);
    }

    public static void main(String[] args) throws Exception {
        CuratorCreateNodeDemo curatorCreateNodeDemo = new CuratorCreateNodeDemo();
//        curatorCreateNodeDemo.create01();
//        curatorCreateNodeDemo.create02();
//        curatorCreateNodeDemo.create03();
        curatorCreateNodeDemo.create04();
    }

}

【a】创建一个节点

我们使用zkCli.sh登录到zookeeper客户端,查看node1节点是否创建成功:

[zk: localhost:2181(CONNECTED) 1] get /create/node1
node1
cZxid = 0x500000003
ctime = Tue Dec 29 11:05:28 CST 2020
mZxid = 0x500000003
mtime = Tue Dec 29 11:05:28 CST 2020
pZxid = 0x500000003
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0

【b】创建一个节点并使用自定义权限列表

可以看到,因为我们node2采用IP地址的授权模式:

[zk: localhost:2181(CONNECTED) 5] get /create/node2
Authentication is not valid : /create/node2

【c】递归创建节点

curator在父节点不存在的时候,会自动帮我们创建父节点,如node3:

[zk: localhost:2181(CONNECTED) 6] ls /create
[node2, node3, node1]
[zk: localhost:2181(CONNECTED) 7] get /create/node3/node31
node31
cZxid = 0x50000000d
ctime = Tue Dec 29 11:09:52 CST 2020
mZxid = 0x50000000d
mtime = Tue Dec 29 11:09:52 CST 2020
pZxid = 0x50000000d
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 6
numChildren = 0

【d】异步方式创建节点

后端日志输出:

11:11:02.643 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorCreateNodeDemo - 节点路径:/node4
11:11:02.644 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorCreateNodeDemo - 事件类型:CREATE

使用zkCli.sh登录到zookeeper客户端,查看node4节点是否创建成功:

[zk: localhost:2181(CONNECTED) 8] get /create/node4       
node4
cZxid = 0x500000010
ctime = Tue Dec 29 11:11:02 CST 2020
mZxid = 0x500000010
mtime = Tue Dec 29 11:11:02 CST 2020
pZxid = 0x500000010
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0

五、curator更新节点

基础代码如下:

package com.wsh.zookeeper.zookeeperapidemo.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CuratorUpdateNodeDemo {

    private static final Logger logger = LoggerFactory.getLogger(CuratorUpdateNodeDemo.class);
    private static final String ZOOKEEPER_SERVER_ADDRESS = "192.168.179.128:2181,192.168.179.129:2181,192.168.179.133:2181";

    /**
     * Curator对象
     */
    private static CuratorFramework curatorFramework;

    static {
        //初始化curator对象
        curatorFramework = CuratorFrameworkFactory
                .builder()
                //会话超时时间
                .sessionTimeoutMs(5000)
                //服务器集群地址
                .connectString(ZOOKEEPER_SERVER_ADDRESS)
                //重试策略
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间,如果制定了命名空间,那么创建的节点的根目录就是/create
                .namespace("update")
                .build();
        //开启客户端
        curatorFramework.start();
    }

    /**
     * 1.更新一个节点
     */
    public void update01() throws Exception {
        curatorFramework
                .setData()
                //节点路径
                .forPath("/update1", "update11".getBytes());
    }

    /**
     * 2. 指定版本号更新节点
     */
    public void update02() throws Exception {
        curatorFramework
                .setData()
                //当且仅当当前节点数据版本号等于指定的版本号时,才更新数据. 指定-1表示版本号不参与更新判断
                .withVersion(20)
                //节点路径
                .forPath("/update2", "update22".getBytes());
    }

    /**
     * 3. 异步方式更新节点
     */
    public void update03() throws Exception {
        curatorFramework
                .setData()
                .inBackground(new BackgroundCallback() {
                    @Override
                    public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                        logger.info("节点路径:" + curatorEvent.getPath());
                        logger.info("事件类型:" + curatorEvent.getType());
                    }
                })
                //节点路径
                .forPath("/update3", "update33".getBytes());
        Thread.sleep(5000);
    }


    public static void main(String[] args) throws Exception {
        CuratorUpdateNodeDemo curatorUpdateNodeDemo = new CuratorUpdateNodeDemo();
//        curatorUpdateNodeDemo.update01();
//        curatorUpdateNodeDemo.update02();
        curatorUpdateNodeDemo.update03();
    }

}

我们事先先创建好三个节点用于测试:

[zk: localhost:2181(CONNECTED) 12] create /update "update"
Created /update
[zk: localhost:2181(CONNECTED) 13] create /update/update1 "update1"
Created /update/update1
[zk: localhost:2181(CONNECTED) 14] create /update/update2 "update2"
Created /update/update2
[zk: localhost:2181(CONNECTED) 15] create /update/update3 "update3"
Created /update/update3
[zk: localhost:2181(CONNECTED) 16] ls /update
[update3, update1, update2]

下面分三种情况测试curator更新节点操作:

【a】更新节点

运行程序,使用客户端查看节点数据是否修改成功:

[zk: localhost:2181(CONNECTED) 17] get /update/update1
update11
cZxid = 0x500000016
ctime = Tue Dec 29 11:23:25 CST 2020
mZxid = 0x50000001a
mtime = Tue Dec 29 11:24:02 CST 2020
pZxid = 0x500000016
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0

【b】指定版本号更新节点

运行程序,我们发现后台报如下图错误:

因为当前节点数据版本号为0,我们指定的版本号是20,显然对不上。

【c】异步方式更新节点

运行程序,查看后端日志:

11:26:28.861 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorUpdateNodeDemo - 节点路径:/update3
11:26:28.861 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorUpdateNodeDemo - 事件类型:SET_DATA

然后我们再使用客户端工具查看节点数据是否更新成功:

[zk: localhost:2181(CONNECTED) 19] get /update/update3
update33
cZxid = 0x500000018
ctime = Tue Dec 29 11:23:28 CST 2020
mZxid = 0x500000023
mtime = Tue Dec 29 11:26:28 CST 2020
pZxid = 0x500000018
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 8
numChildren = 0

六、curator查看节点

基础代码如下:

package com.wsh.zookeeper.zookeeperapidemo.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CuratorGetNodeDateDemo {

    private static final Logger logger = LoggerFactory.getLogger(CuratorGetNodeDateDemo.class);
    private static final String ZOOKEEPER_SERVER_ADDRESS = "192.168.179.128:2181,192.168.179.129:2181,192.168.179.133:2181";

    /**
     * Curator对象
     */
    private static CuratorFramework curatorFramework;

    static {
        //初始化curator对象
        curatorFramework = CuratorFrameworkFactory
                .builder()
                //会话超时时间
                .sessionTimeoutMs(5000)
                //服务器集群地址
                .connectString(ZOOKEEPER_SERVER_ADDRESS)
                //重试策略
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间
                .namespace("get")
                .build();
        //开启客户端
        curatorFramework.start();
    }

    /**
     * 1.读取节点数据
     */
    public void getData01() throws Exception {
        byte[] bytes = curatorFramework.getData().forPath("/get1");
        logger.info("节点数据:" + new String(bytes));
    }

    /**
     * 2. 读取数据时读取节点的属性
     */
    public void getData02() throws Exception {
        Stat stat = new Stat();
        curatorFramework.getData().storingStatIn(stat).forPath("/get1");
        logger.info("节点数据版本号:" + stat.getVersion());
        logger.info("节点创建事务ID:" + stat.getCzxid());
        logger.info("节点创建时间:" + stat.getCtime());
    }

    /**
     * 3. 异步方式读取节点的数据
     */
    public void getData03() throws Exception {
        curatorFramework.getData().inBackground(new BackgroundCallback() {
            @Override
            public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                logger.info("节点路径:" + curatorEvent.getPath());
                logger.info("事件类型:" + curatorEvent.getType());
            }
        }).forPath("/get1");
        Thread.sleep(5000);
    }

    public static void main(String[] args) throws Exception {
        CuratorGetNodeDateDemo curatorGetNodeDateDemo = new CuratorGetNodeDateDemo();
//        curatorGetNodeDateDemo.getData01();
//        curatorGetNodeDateDemo.getData02();
        curatorGetNodeDateDemo.getData03();
    }

}

先用客户端工具创建两个节点用于测试:

[zk: localhost:2181(CONNECTED) 32] create /get "get"
Created /get
[zk: localhost:2181(CONNECTED) 33] create /get/get1 "get1"
Created /get/get1

下面分三种情况测试一下curator查看节点API:

【a】读取节点数据

11:54:41.461 [main] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorGetNodeDateDemo - 节点数据:get1

【b】读取数据时读取节点的属性

11:54:57.172 [main] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorGetNodeDateDemo - 节点数据版本号:0
11:54:57.173 [main] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorGetNodeDateDemo - 节点创建事务ID:21474836538
11:54:57.173 [main] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorGetNodeDateDemo - 节点创建时间:1609214049594

【c】异步方式读取节点的数据

11:55:42.141 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorGetNodeDateDemo - 节点路径:/get1
11:55:42.141 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorGetNodeDateDemo - 事件类型:GET_DATA

七、curator查看子节点

基础代码如下:

package com.wsh.zookeeper.zookeeperapidemo.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

public class CuratorGetChildrenNodeDateDemo {

    private static final Logger logger = LoggerFactory.getLogger(CuratorGetChildrenNodeDateDemo.class);
    private static final String ZOOKEEPER_SERVER_ADDRESS = "192.168.179.128:2181,192.168.179.129:2181,192.168.179.133:2181";

    /**
     * Curator对象
     */
    private static CuratorFramework curatorFramework;

    static {
        //初始化curator对象
        curatorFramework = CuratorFrameworkFactory
                .builder()
                //会话超时时间
                .sessionTimeoutMs(5000)
                //服务器集群地址
                .connectString(ZOOKEEPER_SERVER_ADDRESS)
                //重试策略
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间
                .namespace("children")
                .build();
        //开启客户端
        curatorFramework.start();
    }

    /**
     * 1.读取子节点数据
     */
    public void getChildrenData01() throws Exception {
        List<String> list = curatorFramework.getChildren().forPath("/children1");
        for (String child : list) {
            logger.info("节点路径:" + child);
        }
    }


    /**
     * 2. 异步方式读取子节点的数据
     */
    public void getChildrenData02() throws Exception {
        curatorFramework.getChildren().inBackground(new BackgroundCallback() {
            @Override
            public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                logger.info("节点路径:" + curatorEvent.getPath());
                logger.info("事件类型:" + curatorEvent.getType());
                List<String> children = curatorEvent.getChildren();
                for (String child : children) {
                    logger.info("子节点路径:" + child);
                }
            }
        }).forPath("/children1");
        Thread.sleep(5000);
    }

    public static void main(String[] args) throws Exception {
        CuratorGetChildrenNodeDateDemo curatorGetChildrenNodeDateDemo = new CuratorGetChildrenNodeDateDemo();
//        curatorGetChildrenNodeDateDemo.getChildrenData01();
        curatorGetChildrenNodeDateDemo.getChildrenData02();
    }

}

使用客户端工具先创建好几个节点用于测试:

[zk: localhost:2181(CONNECTED) 34] create /children "children"
Created /children
[zk: localhost:2181(CONNECTED) 35] create /children/children1 "children1"
Created /children/children1
[zk: localhost:2181(CONNECTED) 36] create /children/children1/node1 "node1"    
Created /children/children1/node1
[zk: localhost:2181(CONNECTED) 37] create /children/children1/node2 "node2"
Created /children/children1/node2

下面我们分两种情况测试一下curator查看子节点API:

【a】读取子节点数据

13:38:02.000 [main] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorGetChildrenNodeDateDemo - 节点路径:node2
13:38:02.000 [main] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorGetChildrenNodeDateDemo - 节点路径:node1

【b】异步方式读取子节点数据

13:39:10.309 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorGetChildrenNodeDateDemo - 节点路径:/children1
13:39:10.309 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorGetChildrenNodeDateDemo - 事件类型:CHILDREN
13:39:10.309 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorGetChildrenNodeDateDemo - 子节点路径:node2
13:39:10.309 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorGetChildrenNodeDateDemo - 子节点路径:node1

八、curator删除节点

基础代码如下:

package com.wsh.zookeeper.zookeeperapidemo.curator;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

public class CuratorDeleteNodeDemo {

    private static final Logger logger = LoggerFactory.getLogger(CuratorDeleteNodeDemo.class);
    private static final String ZOOKEEPER_SERVER_ADDRESS = "192.168.179.128:2181,192.168.179.129:2181,192.168.179.133:2181";

    /**
     * Curator对象
     */
    private static CuratorFramework curatorFramework;

    static {
        //初始化curator对象
        curatorFramework = CuratorFrameworkFactory
                .builder()
                //会话超时时间
                .sessionTimeoutMs(5000)
                //服务器集群地址
                .connectString(ZOOKEEPER_SERVER_ADDRESS)
                //重试策略
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                //命名空间
                .namespace("delete")
                .build();
        //开启客户端
        curatorFramework.start();
    }

    /**
     * 1.删除一个节点
     */
    public void delete01() throws Exception {
        curatorFramework.delete().forPath("/delete1");
    }

    /**
     * 2. 指定版本号删除节点
     */
    public void delete02() throws Exception {
        curatorFramework.delete()
                //指定版本号
                .withVersion(20)
                .forPath("/delete2");
    }

    /**
     * 3. 递归删除节点
     */
    public void delete03() throws Exception {
        curatorFramework.delete()
                //当删除节点存在子节点时,一并删除子节点
                .deletingChildrenIfNeeded()
                .forPath("/delete3");
    }

    /**
     * 4. 异步方式删除节点
     */
    public void delete04() throws Exception {
        curatorFramework.delete()
                .inBackground(new BackgroundCallback() {
                    @Override
                    public void processResult(CuratorFramework curatorFramework, CuratorEvent curatorEvent) throws Exception {
                        logger.info("节点路径:" + curatorEvent.getPath());
                        logger.info("事件类型:" + curatorEvent.getType());
                    }
                })
                .forPath("/delete4");
        TimeUnit.SECONDS.sleep(5);
    }

    public static void main(String[] args) throws Exception {
        CuratorDeleteNodeDemo curatorDeleteNodeDemo = new CuratorDeleteNodeDemo();
//        curatorDeleteNodeDemo.delete01();
//        curatorDeleteNodeDemo.delete02();
//        curatorDeleteNodeDemo.delete03();
        curatorDeleteNodeDemo.delete04();
    }

}

先使用客户端创建好几个节点:

[zk: localhost:2181(CONNECTED) 20] create /delete "delete"
Created /delete
[zk: localhost:2181(CONNECTED) 21] create /delete/delete1 "delete1"
Created /delete/delete1
[zk: localhost:2181(CONNECTED) 22] create /delete/delete2 "delete2"
Created /delete/delete2
[zk: localhost:2181(CONNECTED) 23] create /delete/delete3 "delete3"
Created /delete/delete3
[zk: localhost:2181(CONNECTED) 24] create /delete/delete3/node1 "node1"  
Created /delete/delete3/node1
[zk: localhost:2181(CONNECTED) 25] create /delete/delete4 "delete4"    
Created /delete/delete4

下面我们分四种情况分别测试一下curator删除节点的API:

【a】删除一个节点

[zk: localhost:2181(CONNECTED) 26] get /delete/delete1
Node does not exist: /delete/delete1

【b】指定版本号删除节点

当前节点数据版本号如下图:

因为我们程序里面指定的是20,与当前版本对不上,所以后端抛出如下图异常:

【c】递归删除节点

[zk: localhost:2181(CONNECTED) 28] ls /delete/delete3   #删除之前
[node1]
[zk: localhost:2181(CONNECTED) 29] ls /delete/delete3   #删除之后
Node does not exist: /delete/delete3

【d】异步方式删除节点

11:43:36.571 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorDeleteNodeDemo - 节点路径:/delete4
11:43:36.571 [main-EventThread] INFO com.wsh.zookeeper.zookeeperapidemo.curator.CuratorDeleteNodeDemo - 事件类型:DELETE

再次使用客户端查看,可以看到节点已经成功删除。

[zk: localhost:2181(CONNECTED) 30] get /delete/delete4
Node does not exist: /delete/delete4

九、总结

本篇文章主要总结了zookeeper一个开源的客户端curator,并通过案例详细说明了如何使用curator进行节点的创建、修改、删除等操作,更多API操作可以参见curator的官网进行学习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值