单机环境下使用Curator连接zk服务端

1、pom文件与基础类

1.1、pom文件引入依赖

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.7.0</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>5.0.0</version>
    <exclusions>
        <exclusion>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
</dependency>

1.2、基础类

后面每个api的操作都可以通过这个类来获取zookeeper的客户端。

public abstract  class CuratorStandaloneBase {

    private static final String CONNECT_STR = "192.168.231.131:2181";
    private static final int sessionTimeoutMs = 60 * 1000;
    private static final int connectionTimeoutMs = 5000;
    private static CuratorFramework curatorFramework;

    @Before
    public void init() {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(5000, 30);
        curatorFramework = CuratorFrameworkFactory.builder().connectString(getConnectStr())
                .retryPolicy(retryPolicy)
                .sessionTimeoutMs(sessionTimeoutMs)
                .connectionTimeoutMs(connectionTimeoutMs)
                .canBeReadOnly(true)
                .build();
        curatorFramework.getConnectionStateListenable().addListener((client, newState) -> {
            if (newState == ConnectionState.CONNECTED) {
                System.out.println("连接成功!");
            }

        });
        System.out.println("连接中......");
        curatorFramework.start();
    }

    public void createIfNeed(String path) throws Exception {
        Stat stat = curatorFramework.checkExists().forPath(path);
        if (stat==null){
            String s = curatorFramework.create().forPath(path);
            System.out.println("path " + s + " created! ");
        }
    }

    public static CuratorFramework getCuratorFramework() {
        return curatorFramework;
    }

    @After
    public void   test(){
        try {
            TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    protected   String getConnectStr(){
        return CONNECT_STR;
    }
}

2、创建节点

2.1、创建递归节点

Curator内部封装会给我们循环的创建传入路径中的节点。

@Test
public void testCreateWithParent() throws Exception {
    CuratorFramework curatorFramework = getCuratorFramework();

    String pathWithParent = "/node-parent/sub-node-1";
    String path = curatorFramework.create().creatingParentsIfNeeded().forPath(pathWithParent);
    System.out.println("curator create node :" + path + "  successfully.");
}

2.2、一般情况创建节点

@Test
public void testCreate() throws Exception {

    CuratorFramework curatorFramework = getCuratorFramework();
    String forPath = curatorFramework
            .create()
            // protection 模式,防止由于异常原因,导致僵尸节点
            // 在创建节点的时候会去设置一个 UUID.randomUUID().toString() 序号,唯一的
            // 防止在客户端出现网络问题的时候导致节点的重复创建
            .withProtection()
            .withMode(CreateMode.EPHEMERAL_SEQUENTIAL).
                    forPath("/curator-node", "some-data".getBytes());
    System.out.println("curator create node :" + forPath + "  successfully.");
}

这里有一个小的知识点,就是代码中的 .withProtection(),在这个方法中Curator会给节点添加一个UUID,目的是为了防止僵尸节点,什么意思呢,就是当我们从客户端发了一个请求去创建节点,当服务端刚收到了请求然后网络波动了,这个时候客户端就接收不到这个节点被创建成功的信息了,如果是普通节点还好,不能重复创建,但是如果是临时节点,被创建成功了,但是客户端不知道,那么这个节点就会永远存在于服务端,不会被清理掉,这就叫做僵尸节点。点进代码之后就可以看到如下所示:

void resetProtectedId() {
    this.protectedId = UUID.randomUUID().toString();
}

运行截图如下,发现会自动添上一个 UUID。

在这里插入图片描述

3、获取节点数据

@Test
public void testGetData() throws Exception {
    CuratorFramework curatorFramework = getCuratorFramework();

    byte[] bytes = curatorFramework.getData().forPath("/test");
    System.out.println("get data from  node :" + new String(bytes) + "  successfully.");
}

4、修改节点的数据

@Test
public void testSetData() throws Exception {
    CuratorFramework curatorFramework = getCuratorFramework();

    curatorFramework.setData().forPath("/test", "changed!".getBytes());
    byte[] bytes = curatorFramework.getData().forPath("/test");
    System.out.println("get data from  node /test :" + new String(bytes) + "  successfully.");
}

5、删除节点

@Test
public void testDelete() throws Exception {
    CuratorFramework curatorFramework = getCuratorFramework();

    String pathWithParent = "/test";
    curatorFramework.delete().guaranteed().deletingChildrenIfNeeded().forPath(pathWithParent);
}

6、获取该路径下所有的节点

@Test
public void testListChildren() throws Exception {
    CuratorFramework curatorFramework = getCuratorFramework();

    String pathWithParent = "/";
    List<String> strings = curatorFramework.getChildren().forPath(pathWithParent);
    strings.forEach(System.out::println);
}

运行截图如下:

在这里插入图片描述

7、自定义线程池去异步获取数据

在我们原装的连接zk的包里,如果异步获取数据的时候是用的最开始初始化客户端的时候所创建的 EventThread 线程,如果异步的命令很多,或者数据量很大,就会阻塞接收服务端的响应,所以 Curator 给我们提供了可以自定义线程池去执行这些异步操作。

@Test
public void testThreadPool() throws Exception {

    CuratorFramework curatorFramework = getCuratorFramework();
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    String ZK_NODE="/test";
    curatorFramework.getData().inBackground((client, event) -> {
        System.out.println(" background: " + event);
        System.out.println(" data: " + new String(event.getData()) );
    },executorService).forPath(ZK_NODE);
 }

运行截图如下:

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值