1. 简介
Apache Curator 是Netflix公司开源的一个Zookeeper Java客户端操作框架,现在已经是Apache的顶级项目。与Zookeeper提供的原生客户端相比,Curator的抽象层次更高,简化了Zookeeper客户端的开发。并且提供了很多场景下的使用模板,在Curator中称其recipe(菜谱)。
2. Maven
Curator中有许多组件,对于大多数用户来说,使用curator-recipes即可满足需求。
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>2.11.0</version>
</dependency>
3. 操作
3.1 重试策略
curator 有四种重试策略,在创建连接的时候需要指定:
1.RetryUntilElapsed(int maxElapsedTimeMs, int sleepMsBetweenRetries)
以sleepMsBetweenRetries的间隔重连,直到超过maxElapsedTimeMs的时间设置
2.RetryNTimes(int n, int sleepMsBetweenRetries)
指定重连次数
3.RetryOneTime(int sleepMsBetweenRetry)
重连一次
4.ExponentialBackoffRetry
ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries)
ExponentialBackoffRetry(int baseSleepTimeMs, int maxRetries, int maxSleepMs)
每次重连时间的间隔是随机的,但是随着重试次数增加,重试间隔的随机范围上限越高。比如第一次随机范围(1,2),第二次(1,4)依次类推。(见下面公式)
时间间隔=baseSleepTimeMs * Math.max(1, random.nextInt(1 << (retryCount + 1)))
maxSleepMs:超过此时间,则不再重试。
3.2 连接
/* url : zookeeper 地址
* namespace : 起始路径
* id0 : 用户名
* id1 : 密码
* */
public static CuratorFramework buildConnect(String url,String namespace, String id0, String id1)
{
//创建权限管理器
ACLProvider aclProvider = new ACLProvider() {
private List<ACL> acl;
@Override public List<ACL> getDefaultAcl() {
if (acl == null) {
ArrayList<ACL> acl = ZooDefs.Ids.CREATOR_ALL_ACL; //初始化
acl.clear();
acl.add(new ACL(Perms.ALL, new Id("auth", id0 + ":" + id1)));//添加
this.acl = acl;
}
return acl;
}
@Override public List<ACL> getAclForPath(String path) {
return acl;
}
};
CuratorFramework curatorFramework =
CuratorFrameworkFactory.builder()
.aclProvider(aclProvider)
.connectString(url)
.authorization("digest", (id0 + ":" + id1).getBytes()) //使用用户名/密码进行连接
.retryPolicy(new ExponentialBackoffRetry(100, 6)) //重试策略
.build();
curatorFramework.start();
try {
curatorFramework.blockUntilConnected(3, TimeUnit.SECONDS); //阻塞判断连接成功,超时认为失败。
if (curatorFramework.getZookeeperClient().isConnected()) {
return curatorFramework.usingNamespace(namespace); //返回连接,起始根目录为namespace。
}
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
}
// fail situation
curatorFramework.close();
throw new RuntimeException("failed to connect to zookeeper service : " + url);
}
3.3 基本操作
public static void main(String[] args) throws Exception {
//创建连接,CuratorBaseTest类参考上面代码
CuratorFramework curatorFramework = CuratorBaseTest.buildConnect("192.168.10.1:2181,192.168.10.2:2181","test","test","test");
System.out.println("mycat:" + curatorFramework.getData().forPath("/"));
//创建节点
curatorFramework.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/a","test1".getBytes());
//获取数据
System.out.println("data:" + new String(curatorFramework.getData().forPath("/a")));
//设置数据
curatorFramework.setData().forPath("/a", "test2".getBytes());
System.out.println("data:" + new String(curatorFramework.getData().forPath("/a")));
//获取子节点
List<String> list = curatorFramework.getChildren().forPath("/");
for(String s : list)
{
System.out.println("list:"+s);
}
//判断是否存在,stat==null即不存在
Stat stat = curatorFramework.checkExists().forPath("/a");
System.out.println("stat:"+ stat);
//删除节点
curatorFramework.delete().guaranteed().deletingChildrenIfNeeded().forPath("/a");
}