2.ZooKeeper客户端Curator「第三章 ZooKeeper Java客户端」「架构之路ZooKeeper理论和实战」

前言

       上一篇文章 介绍了zookeeper原生API的使用,使用过原生API不得不说,有很多的问题,比如:不能递归创建和删除节点Watcher只能使用一次、还有很多可以解决分布式应用问题的api(比如分布式锁,leader选举等),但由于ZooKeeper提供的原始API并不是很易用,在其基础上封装一些高级应用又是一件很复杂的事情。

       这个时候,Curator出现了,这节我们来看下Curator是什么以及Curator怎么使用。

一、Curator基本概念

1.1 什么是Curator ?

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

       更多的信息可以查看官网:

http://curator.apache.org/index.html

1.2 项目组件

1.3 Maven依赖

       整个框架由下面这些模块组成:

Curator的jar包已经发布到Maven中心,由以下几个artifact的组成。根据需要选择引入具体的artifact。但大多数情况下只用引入curator-recipes即可。

        根据上面的描述,开发人员大多数情况下使用的都是curator-recipes的依赖,此依赖的maven配置如下:

  1. <dependency>
  2. <groupId>org.apache.curator</groupId>
  3. <artifactId>curator-recipes</artifactId>
  4. <version>${version}</version>
  5. </dependency>

1.4 版本说明

       截止到2021年3月18日,最新版本号是:5.1.0。

       通过官网:

http://curator.apache.org/breaking-changes.html

我们可以看到这么一段话:

       核心的一句话就是:ZooKeeper 3.4.x is no longer supported,也就是Curator 5.0 的版本不再支持zk server 是3.4.x的版本了。

       如果你使用zk 3.4.x的版本的话,需要使用之间的版本,click一下:

http://curator.apache.org/zk-compatibility-34.html

       可以看到一段话:

ZooKeeper 3.4.x is now at end-of-life. Consequently, the latest versions of Curator have removed support for it. If you wish to use Curator with ZooKeeper 3.4.x you should pin to version 4.2.x of Curator. Curator 4.2.x supports ZooKeeper 3.4.x ensembles in a soft-compatibility mode. To use this mode you must exclude ZooKeeper when adding Curator to your dependency management tool.

       重点信息就是如果你的ZooKeeper是3.4.x的版本的话,那么Curator要使用4.2.x的版本。

二、Curator入门小栗子

2.1 说明

       我们大体的步骤:

(1)新建一个项目;

(2)引入curator-recipes依赖;

(3)使用CuratorFrameworkFactory构造CuratorFramework对象

(4)使用CuratorFramework的create()进行创作节点。

2.2 新建一个项目

       这里我们新建一个项目;






2.3 添加依赖

       在pom.xml文件中添加依赖curator-recipes和junit:

  1. <dependency>
  2. <groupId>org.apache.curator</groupId>
  3. <artifactId>curator-recipes</artifactId>
  4. <version>5.1.0</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>junit</groupId>
  8. <artifactId>junit</artifactId>
  9. <version>4.13.2</version>
  10. <scope>test</scope>
  11. </dependency>

2.4 编写例子

       我们使用CuratorFrameworkFactory构建一个CuratorFramework,然后使用CuratorFramework的create方法进行创建节点:
 

  1. package com.kfit.test;
  2. import org.apache.curator.RetryPolicy;
  3. import org.apache.curator.framework.CuratorFramework;
  4. import org.apache.curator.framework.CuratorFrameworkFactory;
  5. import org.apache.curator.retry.ExponentialBackoffRetry;
  6. import org.apache.zookeeper.CreateMode;
  7. import org.apache.zookeeper.ZooDefs;
  8. /**
  9. * TODO
  10. *
  11. * @author 悟纤「公众号SpringBoot」
  12. * @date 2021-03-18
  13. * @slogan 大道至简 悟在天成
  14. */
  15. public class CuratorDemo {
  16. public static void main(String[] args) throws Exception {
  17. /*
  18. 方式一:
  19. 重试策略
  20. baseSleepTimeMs: 重试之间等待的初始时间;
  21. maxRetries: 重试的最大次数
  22. */
  23. String connectString= "127.0.0.1:2181";
  24. RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
  25. CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(connectString,retryPolicy);
  26. curatorFramework.start();
  27. /*
  28. 创建一个 允许所有人访问的 持久节点
  29. */
  30. curatorFramework.create()
  31. .creatingParentsIfNeeded()//递归创建,如果没有父节点,自动创建父节点
  32. .withMode(CreateMode.PERSISTENT)//节点类型,持久节点
  33. .withACL(ZooDefs.Ids.OPEN_ACL_UNSAFE)//设置ACL,和原生API相同
  34. .forPath("/curator/test1", "hello".getBytes());
  35. }
  36. }

        执行以下,正常下能够成功的执行,然后zkCli.sh登录下节点:

       集群的情况下,多个地址使用逗号分隔:

String connectString = "127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183,127.0.0.1:2184";

2.5 构建CuratorFramework的其它方式

       对于CuratorFramework的构建可以使用CuratorFrameworkFactory.newClient进行构建:

  1. /*
  2. 方式一:
  3. 重试策略
  4. baseSleepTimeMs: 重试之间等待的初始时间;
  5. maxRetries: 重试的最大次数
  6. * 默认的sessionTimeoutMs为60000
  7. * 默认的connectionTimeoutMs为15000
  8. */
  9. String connectString= "127.0.0.1:2181";
  10. RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
  11. CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(connectString,retryPolicy);
  12. curatorFramework.start();

       对于sessionTimeoutMs和connectionTimeoutMs我们也是可以进行指定的:

CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient(connectString,60000,15000,retryPolicy);

       这种方式就是参数多了,都不知道各个参数是什么意思了,我们看下第二种使用builder的构建方式(推荐使用这种方式):

  1. /*
  2. 方式二:
  3. * connectionString zk地址
  4. * sessionTimeoutMs 会话超时时间
  5. * connectionTimeoutMs 连接超时时间
  6. * namespace 每个curatorFramework 可以设置一个独立的命名空间,之后操作都是基于该命名空间,比如操作 /user/message 其实操作的是/curator/user/message
  7. * retryPolicy 重试策略
  8. */
  9. String connectString = "127.0.0.1:2181";
  10. RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
  11. CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
  12. .connectString(connectString)
  13. .sessionTimeoutMs(60000)
  14. .connectionTimeoutMs(15000)
  15. .namespace("curator")
  16. .retryPolicy(retryPolicy)
  17. .build();
  18. curatorFramework.start();

       这种方法是不是参数一览无遗,看着很舒服。

namespace:为了避免多个应用的节点名称冲突的情况,CuratorFramework提供了命名空间的概念。具体做法是:CuratorFramework会为它的API调用的节点路径的前面自动添加上命名空间。命名空间本质上是从根节点开始的一个路径。之后操作都是基于该命名空间,比如操作 /user/message 其实操作的是/curator/user/message。



购买完整视频,请前往:http://www.mark-to-win.com/TeacherV2.html?id=287