Curator解决了很多ZooKeeper客户端非常底层的细节开发工作,包括连接重连、反复注册Watcher和NodeExistsException异常等,目前已经成为了Apache的顶级项目,是全世界范围内使用最广泛的ZooKeeper客户端之一,Patrick Hunt(ZooKeeper代码的核心提交者)以一句“Guava is to Java what Curator is to ZooKeeper”(Curator对于ZooKeeper,可以说就像Guava工具集对于Java平台一样,作用巨大)对其进行了高度评价。

        除了封装一些开发人员不需要特别关注的底层细节之外,Curator还在ZooKeeper原生API的基础上进行了包装,提供了一套易用性和可读性更强的Fluent风格的客户端API框架。

        除此之外,Curator中还提供了ZooKeeper各种应用场景(Recipe,如共享锁服务、Master选举机制和分布式计数器等)的抽象封装。

Maven依赖

<dependency>

<groupId>org.apache.curator</groupId>

<artifactId>curator.framework</artifactId>

<version>2.4.2</version>

</dependency>

创建会话

        步骤如下。

  • 使用CuratorFrameworkFactory这个工厂类的两个静态方法来创建一个客户端:

static CuratorFramework newClient(String connectString, RetryPolicy retryPolicy);

static CuratorFramework newClient(String connectString, int sessionTimeoutMs, int connectionTimeoutMs, RetryPolicy retryPolicy);

  • 通过调用CuratorFramework中的start()方法来启动会话。

        下表对构造方法中的各参数进行了说明。

参数名说明
connectString指ZooKeeper服务器列表,由英文状态逗号分开的host:port字符串组成,每一个都代表一台ZooKeeper机器,例如,192.168.1.1:2181,192.168.1.2:2181,192.168.1.3:2181
retryPolicy重试策略。默认主要有四种实现,分别是ExponentialBackoffRetry、RetryNTimes、RetryOneTime、RetryUntilElapsed
sessionTimeoutMs会话超时时间,单位为毫秒。默认是60 000ms
connectionTimeoutMs连接创建超时时间,单位为毫秒,默认是15 000ms

        在重试策略上,Curator通过一个接口RetryPolicy来让用户实现自定义的重试策略。在RetryPolicy来让用户实现自定义的重试策略。在RetryPolicy接口中定义了一个方法:

boolean allowRetry(int retryCount, long elapsedTimeMs, RetrySleeper sleeper)

        RetryPolicy接口参数说明如下表所示。

参数名说明
retryCount已经重试的次数。如果是第一次重试,那么该参数为0
elapsedTimeMs从第一次重试开始已经花费的时间,单位为毫秒
sleeper用于sleep指定时间。Curator建议不要使用Thread.sleep来进行操作

使用Curator创建会话

// 使用Curator来创建一个ZooKeeper客户端

public class Create_Session_Sample {

public static void main(String[] args) throws Exception {

RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);

CuratorFramework client = CuratorFrameworkFactory.newClient("domain1.book.zookeeper:2181", 5000, 3000, retryPolicy);

client.start();

Thread.sleep(Integer.MAX_VALUE);

}

}

        在上面这个示例程序中,我们首先创建了一个名为ExponentialBackoffRetry的重试策略,该重试策略是Curator默认提供的几种重试策略之一,其构造方法如下:

  • ExponentialBackOffRetry(int baseSleepTimeMs, int maxRetries);
  • ExponentialBackOffRetry(int baseSleepTimeMs, int maxRetries, int maxSleepMs);

        ExponentialBackoffRetry构造方法参数说明如下表所示。

参数名说明
baseSleepTimeMs初始sleep时间
maxRetries最大重试次数
maxSleepMs最大sleep时间

        ExponentialBackoffRetry的重试策略设计如下。

        给定一个初始sleep时间baseSleepTimeMs,在这个基础上结合重试次数,通过以下公式计算出当前需要sleep的时间:

当前sleep时间 = baseSleepTimeMs * Math.max(1, random.nextInt(1 << (retryCount + 1)))

        可以看出,随着重试次数的增加,计算出的sleep时间会越来越大。如果该sleep时间在maxSleepMs的范围之内,那么就使用该sleep时间,否则使用maxSleepMs。另外,maxRetries参数控制了最大重试次数,以避免无限制的重试。

        从上面的示例程序中还可以看出,CuratorFrameworkFactory工厂在创建出一个客户端CuratorFramework实例之后,实质上并没有完成会话的创建,而是需要调用CuratorFramework的start()方法来完成会话的创建。

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

        Curator提供的API接口在设计上最大的亮点在于其遵循了Fluent设计风格,这也是和ZooKeeper原生API以及ZkClient客户端有很大不同的地方。

// 使用Fluent风格的API接口来创建一个ZooKeeper客户端

public class Create_Session_Sample_fluent {

public static void main(String[] args) throws Exception {

RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);

CuratorFramework client = CuratorFrameworkFactory.builder().connectString("domain1.book.zookeeper:2181").sessionTimeoutMs(5000).retryPolicy(retryPolicy).build();

client.start();

Thread.sleep(Integer.MAX_VALUE);

}

}

使用Curator创建含隔离命名空间的会话

        为了实现不同的ZooKeeper业务之间的隔离,往往会为每个业务分配一个独立的命名空间,即指定一个ZooKeeper根路径。例如,下面所示的代码片段中定义了某一个客户端的独立命名空间为/base,那么该客户端对ZooKeeper上数据节点的任何操作,都是基于该相对目录进行的:

CuratorFrameworkFactory.builder().connectString("domain1.book.zookeeper:2181").sessionTimeoutMs(5000).retryPolicy(retryPolicy).namespace("base").build();

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐