Curator基本操作笔记

分类

Zookeeper客户端

创建ZKClient

ZKClient在Curator中的具体实现是CuratorFrameWork,可以通过构造函数和Fluent方式进行构建。

CuratorFrameWork

public CuratorFramework getCurator(){
        CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
                .connectString("127.0.0.1:2181")
                .sessionTimeoutMs(5000)
                .connectionTimeoutMs(1000)
                .retryPolicy(new ExponentialBackoffRetry(1000,3))
                .build();
        Assertions.assertThat(curatorFramework).isNotNull();
        return curatorFramework;
}

retryPolicy

参数RetryPolicy指的是在CuratorFramework进行连接的时候进行的重试策略,实现自定义的RetryPolicy需要重写allowRetry(int retryCount, long elapsedTimeMs, RetrySleeper sleeper)方法
这里我使用的是Curator提供的ExponentialBackoffRetry类,它集成了RetryPolicy的子类SleepingRetry,每次重试都会随机的将基础睡眠时间延长一段时间,具体代码如下:

   @Override
    protected int getSleepTimeMs(int retryCount, long elapsedTimeMs)
    {
        // copied from Hadoop's RetryPolicies.java
        int sleepMs = baseSleepTimeMs * Math.max(1, random.nextInt(1 << (retryCount + 1)));
        if ( sleepMs > maxSleepMs )
        {
            log.warn(String.format("Sleep extension too large (%d). Pinning to %d", sleepMs, maxSleepMs));
            sleepMs = maxSleepMs;
        }
        return sleepMs;
    }

Curator版本和Zookeeper版本适配

Curator3.*版本只支持Zookeeper3.5.*版本,使用3.4.*版本的方法,有两种方式:

  1. 更换为低版本Curator2.*
  2. 在依赖中移除内置的zookeeper依赖,具体pom如下:
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>${curator-version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </exclusion>
    </exclusions>
</dependency>

zooKeeper基本操作

关于zooKeeper的基本操作,都是使用junit写出的单元测试进行操作的

同步创建删除查看节点

@Test
    void createNodeAndDeleteNodeTest() throws Exception {
        //创建节点
        String path = curatorFramework.create()
                .creatingParentsIfNeeded()
                .withMode(CreateMode.EPHEMERAL)
                .forPath("/test/123", "test".getBytes());
        Assertions.assertThat(path).isEqualTo("/test/123");
        //获取节点数据以及节点状态
        Stat stat = new Stat();
        String data = new String(curatorFramework.getData()
                .storingStatIn(stat)
                .forPath("/test/123"));
        Assertions.assertThat(stat).isNotNull();
        Assertions.assertThat(data).isEqualTo("test");
        //修改节点数据
        curatorFramework.setData().withVersion(stat.getVersion()).forPath("/test/123", "test123".getBytes());
        Assertions.assertThat(new String(curatorFramework.getData()
                .storingStatIn(stat)
                .forPath("/test/123"))).isEqualTo("test123");
        //获取子节点
        List<String> children = curatorFramework.getChildren().forPath("/test");
        Assertions.assertThat(children).contains("123");
        //删除节点
        curatorFramework.delete()
                .guaranteed()
                .deletingChildrenIfNeeded()
                .forPath("/test");
        Assertions.assertThat(curatorFramework.checkExists().forPath("/test/123")).isNull();
    }

异步创建删除查看节点

@Test
    void asyncCreateNodeAndDeleteNodeTest() throws Exception {
        //线程池
        ExecutorService service = Executors.newFixedThreadPool(5);
        //创建节点
        curatorFramework.create()
                .creatingParentsIfNeeded()
                .withMode(CreateMode.EPHEMERAL)
                .inBackground((arg0, arg1) ->
                        {
                            Assertions.assertThat(arg1.getPath()).isEqualTo("/test/123");
                            Assertions.assertThat(arg1.getType()).isEqualTo(CuratorEventType.CREATE);
                            Assertions.assertThat(arg1.getContext()).isEqualTo("123");
                        }
                        , "123", service)
                .forPath("/test/123", "test".getBytes());
        //修改节点数据
        curatorFramework.setData()
                .inBackground((arg0, arg1) ->
                {
                    Assertions.assertThat(arg1.getType()).isEqualTo(CuratorEventType.SET_DATA);
                }, service)
                .forPath("/test/123", "test123".getBytes());
        //获取子节点
        curatorFramework.getChildren().inBackground((arg0, arg1) ->
                {
                    Assertions.assertThat(arg1.getChildren()).contains("123");
                    Assertions.assertThat(arg1.getType()).isEqualTo(CuratorEventType.CHILDREN);
                }
                , service).forPath("/test");
        //删除节点
        curatorFramework.delete()
                .guaranteed()
                .deletingChildrenIfNeeded()
                .forPath("/test");
        Assertions.assertThat(curatorFramework.checkExists().forPath("/test/123")).isNull();
        service.shutdown();
    }

节点数据事件监听器

    @Test
    void nodeListenerTest() throws Exception {
        NodeCache cache = new NodeCache(curatorFramework, "/test/123");
        cache.start();
        cache.getListenable().addListener(() -> {
            log.info(new String(cache.getCurrentData().getData()));
        });
        curatorFramework.create()
                .creatingParentsIfNeeded()
                .withMode(CreateMode.EPHEMERAL)
                .forPath("/test/123", "test".getBytes());
        for (int i = 0; i < 10; i++) {
            curatorFramework.setData().forPath("/test/123", String.valueOf(Math.random()).getBytes());
            Thread.sleep(1000);
        }
        curatorFramework.delete()
                .guaranteed()
                .deletingChildrenIfNeeded()
                .forPath("/test");
        Assertions.assertThat(curatorFramework.checkExists().forPath("/test/123")).isNull();

    }

子节点事件监听器

    @Test
    void nodeChildrenListenerTest() throws Exception {
        PathChildrenCache cache = new PathChildrenCache(curatorFramework, "/test/123", true);
        cache.start();
        cache.getListenable().addListener((client, event) -> {
            switch (event.getType()) {
                case CHILD_ADDED:
                    log.info("child_added "+event.getData());
                    break;
                case CHILD_REMOVED:
                    log.info("child_added "+event.getData());
                    break;
                case CHILD_UPDATED:
                    log.info("child_added "+event.getData());
                    break;
                default:
                    log.info("other event "+event.getData());
            }
        });
        for (int i = 0; i < 10; i++) {
            curatorFramework.create()
                    .creatingParentsIfNeeded()
                    .withMode(CreateMode.EPHEMERAL)
                    .forPath("/test/123/"+String.valueOf(Math.random()), "test".getBytes());
            Thread.sleep(1000);
        }
        curatorFramework.delete()
                .guaranteed()
                .deletingChildrenIfNeeded()
                .forPath("/test");
        Assertions.assertThat(curatorFramework.checkExists().forPath("/test/123")).isNull();
    }

领导选举示例

基本原理

服务启动

1.每个服务节点与Zookeeper保持连接并且将自己注册到节点/child/服务ID上。
2.判断当前是否有Master,如果没有,尝试注册成为Master节点,如果失败,就再次查询master节点,并将master数据记录下来
3.在注册过程中,如果发现之前的Master节点并不是自己,延迟一段时间在进行注册,避免网络抖动导致的频繁易主问题。
4.设置master节点的监听器,当收到节点删除的事件时,再次进行争抢master节点的操作

服务关闭

删除节点,查看自己是否为master节点,如果是,释放该节点

猜你喜欢

转载自blog.csdn.net/xinhongyang/article/details/79902104