java 使用curator读zookeeper进行连接操作(创建、更新、删除、监听)

Curator是一套由netflix公司开源的,Java语言编程的zookeeper客户端框架,Curator项目是现在Zookeeper客户端使用最多的,对Zookeeper版本支持最好的第三方客户端,并推荐使用,Curator把我们平常常用的很多Zookeeper服务开发功能做了封装,例如Leader选举、分布式计数器、分布式锁。这就减少了技术人员在使用zookeeper时的大部分底层细节开发工作。在会话重新连接、Watch反复注册时,由于对其这些功能都做了高度的封装,使用起来更加简单,不但减少了开发时间,而且增强了程序的可靠性。

这是我们以maven工程为例,首先要引入Curator框架相关的开发包,这里为了方便测试引入了junit,lombok,由于Zookeeper本身以来了log4j日志框架,所以这里可以创建对应的log4j配置文件后直接使用。如下面的代码所示,我们通过将Curator相关的引用包配置到Maven工程的pom文件中,将Curator框架引用到工程项目里,在配置文件中分别应用里两个Curator相关的包,第一个是curator-framework包,该包是对zookeeper底层API的一些封装。另一个是curator-recipes包,该包封装了一些Zookeeper服务的高级特性,如:Cache时间监听、选举、分布式锁、分布式barrier。

<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>

创建会话

使用fluent风格创建

RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        CuratorFramework client = CuratorFrameworkFactory.builder().connectString("localhost:2181").sessionTimeoutMs(5000).connectionTimeoutMs(5000)
                .retryPolicy(retryPolicy).build();
        client.start();

这段代码的编码风格采用了流式编程方式,最核心的是CuratorFramework类,该类的作用是定义一个zookeeper客户端对象,并在之后的上下文中使用。在定义CuratorFramework对象实例的时候,我们使用CuratorFramework类,该类的作用是定义一个zookeeper客户端对象,并在之后的上下文中使用。在定义CuratorFramework对象实例的时候,我们使用了CuratorFrameworkFactory工厂方法,并指定了connectiongString 服务器地址列表、retryPolicy重试策略、sessionTimeoutMs会话超时时间。下面我们分别对这几个参数进行详解。

connectingString:服务器地址列表,在指定服务器地址列表的时候可以是一个地址,可以是多个地址。如果是多个地址,那么每个服务器地址列表用逗号分隔,如host1:port1,host2:port2,host3:port3

retryPolicy:重试策略,当客户端异常退出或者与服务端失去连接时候,可以通过设置客户端重新连接Zookeeper服务端。而Curator提供了一次重试、多次重试等不同种类的实现方式。在Curator内部,可以通过判断服务器返回keeperException的状态码来判断是否进行重试处理,如果返回的是OK表示一切操作都没有问题,而SYSTEMERROR表示系统或服务端错误。

ExponentialBackoffRetry:重试一组次数,重试之间的睡眠时间增加

RetryNTimes:重试最大次数

RetryOneTime:只重试一次

RetryUnitElapsed:在指定的时间结束之前重试

超时时间:Curator客户端创建过程中,有两个超时时间的设置。一个是sessionTimeoutMs会话超时时间,用来设置该条会话在Zookeeper服务端的失效时间。另一个是connectionTimeoutMs 客户端创建会话的超时时间,用来限制客户端发起一个会话连接到接收Zookeeper服务端应答的时间。SessionTimeoutMs作用在服务端,而connectionTimeoutMs作用在客户端

创建节点

private static void createNode() throws Exception {
        String path = initZookeeperClient().create().forPath("/curator-node111");
        log.info("curator create node:{} successfully",path);
    }

在Curator中,可以使用create函数创建数据节点,并通过withMode函数指定节点类型(持久化节点,临时节点,顺序节点,顺序临时节点,持久化顺序节点等),默认是持久化节点,之后调用forPath函数来指定节点的路径和数据信息。

一次性创建带层级结构的节点

private static void createNodeLevel() throws Exception {
        String path = initZookeeperClient().create().creatingParentsIfNeeded().forPath("/node-parent/sub-ndoe1");
        log.info("curator create node:{} successfully",path);
    }

获取数据

private static void getNode() throws Exception {
        byte[] bytes = initZookeeperClient().getData().forPath("/curator-node");
        log.info("get data from node: {} successfully",new String(bytes));
    }

更新节点

我们通过客户端实例的setData()方法更新Zookeeper服务上的数据节点,在setData方法的后边,通过forPath函数指定更新的数据节点路径以及要更新的数据。

private static void updateNode() throws Exception {
        initZookeeperClient().setData().forPath("/curator-node","changed".getBytes());
        byte[] by = initZookeeperClient().getData().forPath("/curator-node");
        log.info("get data:{}",new String(by));
    }

删除节点

private static void deleteNode() throws Exception {
        initZookeeperClient().delete().guaranteed().deletingChildrenIfNeeded().forPath("/curator-node");
    }

guaranteed:该函数的功能如字面意思一样,主要起到一个保障删除成功的作用,其底层工作的方式:只要客户端的会话有效,就会在后台持续发起删除请求,直到该数据节点在Zookeeper服务端被删除。

deletingChildIfNeeded:指定了该函数后,系统在删除该数据节点的时候会以递归的方式直接删除其子节点,以及节点的子节点。

异步接口

Curator引入了BackgroundCallback接口,用来处理服务端返回来的信息,这个处理过程是在异步线程中调用,默认在EventThread中调用,可以以自定义线程池。指定

private static void asyncGetData() throws Exception {
        initZookeeperClient().getData().inBackground((item1,item2) -> {

            log.info("background item1:{}  ",item1);
            log.info("background itme2:{}  " ,new String(item2.getData()));
        }).forPath("/curator-node");
        TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
    }

指定线程池

private static void threadPool() throws Exception {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        initZookeeperClient().getData().inBackground((item1,item2) -> {
            log.info("background:{}",new String(item2.getData()));
            System.out.println("dfdffdsfsf");
        },executorService).forPath("/curator-node");
        TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
    }

Curator监听器

针对background通知和错误通知。使用此监听器之后,调用inBackground方法会异步获得监听。

Curator 引入了Cache来实现对Zookeeper服务端事件进行监听,Cache事件监听可以理解为一个本地缓存缓存视图与远程Zookeeper视图的对比过程。Cache提供了反复注册的功能。Cache分别为两类注册类型:节点监听和子节点监听。

NodeCache对某一个节点进行监听

private static void monitorNode() throws Exception {
        NodeCache nodeCache = new NodeCache(initZookeeperClient(), "/curator-node111");
        nodeCache.getListenable().addListener(new NodeCacheListener() {
            @Override
            public void nodeChanged() throws Exception {
                log.info("{},path nodecached","/curator-node");
            }
        });
        TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
        nodeCache.start(true);
    }

pathCache

PathChildrenCache 会对子节点进行监听,但是不会对二级子节点进行监听

PathChildrenCache pathChildrenCache = new PathChildrenCache(initZookeeperClient(), "/path‐cache", true);
        pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() {
            @Override
            public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
                log.info("event:{}",pathChildrenCacheEvent);
            }
        });
        pathChildrenCache.start(true);

tree cache:

TreeCache 使用一个内部类TreeNode来维护这个一个树结构。并将这个树结构与ZK节点进行了映射。所以TreeCache可以监听当前节点下的所有节点的事件

TreeCache treeCache = new TreeCache(initZookeeperClient(), "/tree-path");
        treeCache.getListenable().addListener(new TreeCacheListener() {
            @Override
            public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
                log.info("tree cache:{}",treeCacheEvent.toString());
            }
        });
        treeCache.start();
        TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值