ZooKeeper客户端Curator的基本使用

前提:ZooKeeper版本:3.4.14      Curator版本:2.13.0 


1.什么是Curator

       Curator是Netflix公司开源的一套zookeeper客户端框架,解决了很多Zookeeper客户端非常底层的细节开发工作,是一个比较完善的ZooKeeper客户端框架,通过封装的一套高级API 简化了ZooKeeper的操作。

        在Curator出现之前,我们可以通过zookeeper自带的客户端zkCli来访问,也可以通过Java API来对zookeeper中数据进行相关操作。为了更好的实现Java类操作zookeeper服务器,后来出现了Curator框架,非常的强大,目前已经是Apache的顶级项目,里面提供了更多丰富的操作。例如session超时重连、主从选举、分布式计数器、分布式锁等等适用于各种复杂的zookeeper场景的API封装。并且还提供了一套Fluent风格的操作API,Curator框架使用链式编程风格,易读性更强。


2.Java中使用Curator准备工作

  1.Java中使用,我们需要添加curator的maven依赖

      curator-framework:对zookeeper的底层api的一些封装

      curator-recipes:封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等

<!-- 添加curator支持-->
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>4.0.0</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>4.0.0</version>
</dependency>

  2.完成对API的了解


3.Curator中API介绍

   1.获取Curator客户端会话连接(共有3种方式获取)

     ①使用工厂方法获取Curator客户端会话

public CuratorFramework getCuratorInstanceWithFactory(){
    //配置重试策略(内建有四种重试策略,也可以自行实现RetryPolicy接口)
    RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
    //使用默认的sessionTimeout和connectionTimeout获取连接
    CuratorFramework client = CuratorFrameworkFactory.newClient("192.168.204.201:2181,192.168.204.202:2181,192.168.204.203:2181", retryPolicy);
    //启动Curator客户端
    client.start();
    return client;
}

构造方法:ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries)

                  ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries,int maxSleepMs)

参数名说明
baseSleepTimeMs初始化Sleep时间
maxRetries最大重试次数
maxSleepMs(三个参数的构造方法)最大Sleep时间(默认值:2147483647)
构造方法:CuratorFramework newClient(String connectString, RetryPolicy retryPolicy)
                  CuratorFramework newClient(String connectString, int sessionTimeoutMs, int connectionTimeoutMs, RetryPolicy retryPolicy)
参数名说明
connectStringZooKeeper服务地址(String,多个用逗号分隔)
retryPolicy重试策略
sessionTimeoutMs会话超时时间(单位:ms   默认值:60000)
connectionTimeoutMs连接超时时间(单位:ms  默认值:15000)

     ②使用Fluent风格的API来创建会话

public CuratorFramework getCuratorInstanceWithFluent(){
    RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
    CuratorFramework client = CuratorFrameworkFactory.builder()
                                .connectString("192.168.204.201:2181,192.168.204.202:2181,192.168.204.203:2181")
                                .sessionTimeoutMs(40000)
                                .connectionTimeoutMs(10000)
                                .retryPolicy(retryPolicy)
                                .build();
    client.start();
    return client;
}

    ③创建带命名空间的会话

       为了实现不同的Zookeeper业务之间的隔离,需要为每个业务分配一个独立的命名空间(namespace),即指定一个Zookeeper的根路径。在多个应用共用一个Zookeeper集群的场景下,这对于实现不同应用之间的相互隔离十分有意义

public CuratorFramework getCuratorInstanceWithNamespace(){
    RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
    CuratorFramework client = CuratorFrameworkFactory.builder()
                                .connectString("192.168.204.201:2181,192.168.204.202:2181,192.168.204.203:2181")
                                .sessionTimeoutMs(40000)
                                .connectionTimeoutMs(10000)
                                .retryPolicy(retryPolicy)
                                .namespace("/xxx")
                                .build();
    client.start();
    return client;
}

  2.创建zNode数据节点(zookeeper节点)

    节点数据类型分为如下4种:

  • PERSISTENT:持久化(默认)
  • PERSISTENT_SEQUENTIAL:持久化并且带序列号
  • EPHEMERAL:临时
  • EPHEMERAL_SEQUENTIAL:临时并且带序列号
public void createNode(CuratorFramework client){
    try {
        //1.创建一个节点(如果没有设置节点属性,默认为持久节点,未设值,我测试是一个:192.168.204.1,不应该是空吗)
        client.create().forPath("/path");

        //2.创建一个持久节点(指定值)
        client.create().forPath("/path","value".getBytes());

        //3.创建指定类型节点(临时节点)
        //共有7种类型,常用的4种(PERSISTENT(持久),PERSISTENT_SEQUENTIAL(持久有序),EPHEMERAL(临时),EPHEMERAL_SEQUENTIAL(临时有序),CONTAINER,PERSISTENT_WITH_TTL,PERSISTENT_SEQUENTIAL_WITH_TTL)
        client.create().withMode(CreateMode.EPHEMERAL).forPath("/path","value".getBytes());

        //4.递归创建节点(creatingParentsIfNeeded()方法表示:如果父节点不存在,连带一起创建)
        client.create().creatingParentsIfNeeded().forPath("/path/childPath","value".getBytes());
        //这个creatingParentContainersIfNeeded()接口非常有用,因为一般情况开发人员在创建一个子节点必须判断它的父节点是否存在,如果不存在直接创建会抛出NoNodeException,使用creatingParentContainersIfNeeded()之后Curator能够自动递归创建所有所需的父节点。
    } catch (Exception e) {
        e.printStackTrace();
    }
}

  3.获取某个节点的数据

public void getNode(CuratorFramework client){
    try {
        //1.获取某个节点的数据
        byte[] bytes = client.getData().forPath("/path1");
        System.out.println(new String(bytes));
        //2.获取某个节点的数据 && 同时获取该节点的Stat数据
        Stat stat = new Stat();
        byte[] bytes1 = client.getData().storingStatIn(stat).forPath("/path1");
        System.out.println(stat);
        System.out.println(new String(bytes1));
        //3.获取某个节点下的所有子节点
        List<String> childs = client.getChildren().forPath("/");
        System.out.println(Arrays.asList(childs));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

  4.更新zNode节点的数据

public void setNodeData(CuratorFramework client){
    try {
        //1.更新节点数据内容
        client.setData().forPath("/path","lzb".getBytes());
        //2.指定版本数据内容更新(根据getData获取stat信息)
        Stat stat = new Stat();
        client.getData().storingStatIn(stat).forPath("/path");
        client.setData().withVersion(stat.getVersion()).forPath("/path","lzb come on".getBytes());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

  5.删除zNode节点数据

public void deleteNode(CuratorFramework client){
    try {
        //1.删除节点(该方法只能删除一个节点,如该节点有子节点,报错)
        client.delete().forPath("/path");
        //2.指定版本节点删除(根据getData获取stat信息)
        Stat stat = new Stat();
        client.getData().storingStatIn(stat).forPath("/path1");
        client.delete().withVersion(stat.getVersion()).forPath("/path1");
        //3.递归删除节点(有子节点的,递归全部删除)
        client.delete().deletingChildrenIfNeeded().forPath("/path3");
        //4.强制删除节点,直到删除成功
        client.delete().guaranteed().forPath("/path11");
        //guaranteed()接口是一个保障措施,只要客户端会话有效,那么Curator会在后台持续进行删除操作,直到删除节点成功。
    } catch (Exception e) {
        e.printStackTrace();
    }
}

  6.检查是否存在某个节点

public void checkExist(CuratorFramework client){
    try {
        //检查是否存在某个节点
        Stat stat = client.checkExists().forPath("/path");
        System.out.println(stat);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

4.监听

       Zookeeper原生支持通过注册Watcher来进行事件监听,但是开发者需要反复注册(Watcher只能单次注册单次使用)。Cache是Curator中对事件监听的包装,可以看作是对事件监听的本地缓存视图,能够自动为开发者处理反复注册监听。Curator提供了三种Watcher(Cache)来监听结点的变化。

1.PathChildrenCache  监听一个节点下子节点的创建、删除、更新操作
2.NodeCache 监听一个节点的更新和创建事件
3.TreeCache 综合PathChildrenCache和NodeCache的特性

 1.PathChildrenCache监听(监听一个节点下子节点的创建、删除、更新操作

/**
 * PathChildrenCache 监听一个节点下子节点的创建、删除、更新操作
 * @param client
 * @param path
 */
public static void addListenerWithPathChildrenCache(CuratorFramework client,String path){
    try {
        PathChildrenCache pathChildrenCache = new PathChildrenCache(client,path,true);
        PathChildrenCacheListener pathChildrenCacheListener = new PathChildrenCacheListener() {
            public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
                System.out.println("Receive Event:"+ pathChildrenCacheEvent.getType());
            }
        };
        pathChildrenCache.getListenable().addListener(pathChildrenCacheListener);
        pathChildrenCache.start(PathChildrenCache.StartMode.NORMAL);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

 2.NodeCache监听(用于监听一个节点的更新和创建事件)

/**
 * NodeCache 用于监听一个节点的更新和创建事件
 * 当创建节点,或者更新节点信息时,会监听到
 */
public static void addListenerWithNodeCache(CuratorFramework client,String path){
    try {
        final NodeCache nodeCache = new NodeCache(client,path,false);
        NodeCacheListener nodeCacheListener = new NodeCacheListener() {
            public void nodeChanged() throws Exception {
                System.out.println("Receive Event:"+nodeCache.getCurrentData().getPath());
            }
        };
        nodeCache.getListenable().addListener(nodeCacheListener);
        nodeCache.start();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

3.TreeCache综合节点监听(PathChildrenCache和NodeCache的特性)

/**
 * TreeCache 综合节点监听事件(PathChildrenCache和NodeCache的特性)
 * @param client
 * @param path
 */
public static void addListenerWithTreeCache(CuratorFramework client,String path){
    try {
        TreeCache treeCache = new TreeCache(client,path);
        TreeCacheListener treeCacheListener = new TreeCacheListener() {
            public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
                System.out.println(treeCacheEvent.getType() + "-->" + treeCacheEvent.getData().getPath());
            }
        };
        treeCache.getListenable().addListener(treeCacheListener);
        treeCache.start();

    } catch (Exception e) {
        e.printStackTrace();
    }
}

Curator高级属性,感觉这位博主写的很棒。本篇就不做更多介绍,只做基本使用介绍。

请参考:Zookeeper客户端Curator使用详解


博主写作不易,来个关注呗

求关注、求点赞,加个关注不迷路 ヾ(◍°∇°◍)ノ゙

博主不能保证写的所有知识点都正确,但是能保证纯手敲,错误也请指出,望轻喷 Thanks♪(・ω・)ノ

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扛麻袋的少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值