Curator客户端的基本操作

疯狂创客圈 Java 分布式聊天室【 亿级流量】实战系列之 -24【 博客园 总入口


写在前面

​ 大家好,我是作者尼恩。目前和几个小伙伴一起,组织了一个高并发的实战社群【疯狂创客圈】。正在开始高并发、亿级流程的 IM 聊天程序 学习和实战

​ 前面,已经完成一个高性能的 Java 聊天程序的四件大事:

接下来,需要进入到分布式开发的环节了。 分布式的中间件,疯狂创客圈的小伙伴们,一致的选择了zookeeper,不仅仅是由于其在大数据领域,太有名了。更重要的是,很多的著名框架,都使用了zk。

本篇介绍 Curator客户端的基本操作

1.1.1. Curator客户端的依赖包

打开Curator的官网,我们可以看到,Curator包含了以下几个包:

curator-framework:对zookeeper的底层api的一些封装;

curator-client:提供一些客户端的操作,例如重试策略等;

curator-recipes:封装了一些高级特性,如:Cache事件监听、选举、分布式锁、分布式计数器、分布式Barrier等。

Maven依赖(使用curator的版本:4.0.0,对应Zookeeper的版本为:3.4.x,如果版本不匹配,就会有兼容性问题,很有可能导致节点操作失败。具体的版本对应关系,可以去curator的官网查看。

   <dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>4.0.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency> <dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.0.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>

1.1.2. Curator 创建会话

使用 curator-framework 包中的工厂类CuratorFrameworkFactory中的静态方法newClient,来创建客户端会话。

代码如下:

/**
* create by 尼恩 @ 疯狂创客圈
**/
public class ClientFactory { /**
* @param connectionString zk的连接地址
* @return CuratorFramework 实例
*/
public static CuratorFramework createSimple(String connectionString) {
// 重试策略:第一次重试等待1s,第二次重试等待2s,第三次重试等待4s
// 第一个参数:等待时间的基础单位,单位为毫秒
// 第二个参数:最大重试次数
ExponentialBackoffRetry retryPolicy =
new ExponentialBackoffRetry(1000, 3); // 获取 CuratorFramework 实例的最简单的方式
// 第一个参数:zk的连接地址
// 第二个参数:重试策略
return CuratorFrameworkFactory.newClient(connectionString, retryPolicy);
} /**
* @param connectionString zk的连接地址
* @param retryPolicy 重试策略
* @param connectionTimeoutMs 连接
* @param sessionTimeoutMs
* @return CuratorFramework 实例
*/
public static CuratorFramework createWithOptions(
String connectionString, RetryPolicy retryPolicy,
int connectionTimeoutMs, int sessionTimeoutMs) { // builder 模式创建 CuratorFramework 实例
return CuratorFrameworkFactory.builder()
.connectString(connectionString)
.retryPolicy(retryPolicy)
.connectionTimeoutMs(connectionTimeoutMs)
.sessionTimeoutMs(sessionTimeoutMs)
// 其他的创建选项
.build();
}
}

这里用到两个版本,前一个是简化版本,只需要设置ZK集群的连接地址和重试策略。

后一个是相对复杂的重载版本,可以设置连接超时connectionTimeoutMs、会话超时sessionTimeoutMs 等其他的会话创建选项。

具体请看疯狂创客圈的Demo源码。

1.1.3. CRUD 之 Create 创建节点

使用create()方法,最后使用forPath带上需要创建的节点路径。

    /**
* 创建节点
*/
@Test
public void createNode() {
//创建客户端
CuratorFramework client = ClientFactory.createSimple(ZK_ADDRESS);
try {
//启动客户端实例,连接服务器
client.start(); // 创建一个 ZNode 节点
// 节点的数据为 payload String data = "hello";
byte[] payload = data.getBytes("UTF-8");
String zkPath = "/test/CRUD/node-1";
client.create()
.creatingParentsIfNeeded()
.withMode(CreateMode.PERSISTENT)
.forPath(zkPath, payload); } catch (Exception e) {
e.printStackTrace();
} finally {
CloseableUtils.closeQuietly(client);
}
}

使用withMode()方法,设置节点的类型。zookeeper节点有四种类型:

(1)PERSISTENT 持久节点

(2)PERSISTENT_SEQUENTIAL 持久顺序节点

(3)PHEMERAL 临时节

(4)EPHEMERAL_SEQUENTIAL 临时顺序节点

下面详细介绍一下四种节点的区别和联系。

(1)持久节点(PERSISTENT)

所谓持久节点,是指在节点创建后,就一直存在,直到有删除操作来主动清除这个节点。持久节点的生命周期是永久有效,不会因为创建该节点的客户端会话失效而消失。

(2)持久顺序节点(PERSISTENT_SEQUENTIAL)

这类节点的生命周期和持久节点是一致的。额外的特性是,在ZK中,每个父节点会为他的第一级子节点维护一份次序,会记录每个子节点创建的先后顺序。如果在创建子节点的时候,可以设置这个属性,那么在创建节点过程中,ZK会自动为给定节点名加上一个表示次序的数字后缀,作为新的节点名。这个次序后缀的范围是整型的最大值。

比如,在创建节点的时候只需要传入节点 “/test_”,这样之后,zookeeper自动会给”test_”后面补充数字次序。

(3)临时节点(EPHEMERAL)

和持久节点不同的是,临时节点的生命周期和客户端会话绑定。也就是说,如果客户端会话失效,那么这个节点就会自动被清除掉。注意,这里提到的是会话失效,而非连接断开。这里还要注意一件事,就是当你客户端会话失效后,所产生的节点也不是一下子就消失了,也要过一段时间,大概是10秒以内,可以试一下,本机操作生成节点,在服务器端用命令来查看当前的节点数目,你会发现客户端已经stop,但是产生的节点还在。

另外,在临时节点下面不能创建子节点。

(4)临时顺序节点(EPHEMERAL_SEQUENTIAL)

此节点是属于临时节点,不过带有顺序,客户端会话结束节点就消失。

1.1.4. CRUD 之Read获取节点

与节点读取的有关的方法,主要有三个:

(1)首先是判断节点是否存在,使用checkExists方法。

(2)其次是获取节点的数据,使用getData方法。

(3)最后是获取子节点列表,使用getChildren方法。

演示代码如下:

 /**
* 读取节点
*/
@Test
public void readNode() {
//创建客户端
CuratorFramework client = ClientFactory.createSimple(ZK_ADDRESS);
try {
//启动客户端实例,连接服务器
client.start(); String zkPath = "/test/CRUD/node-1"; Stat stat = client.checkExists().forPath(zkPath);
if (null != stat) {
//读取节点的数据
byte[] payload = client.getData().forPath(zkPath);
String data = new String(payload, "UTF-8");
log.info("read data:", data); String parentPath = "/test";
List<String> children = client.getChildren().forPath(parentPath); for (String child : children) {
log.info("child:", child);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
CloseableUtils.closeQuietly(client);
}
}

1.1.5. CRUD 之update更新节点

节点的更新,分为同步更新与异步更新。

    /**
* 更新节点
*/
@Test
public void updateNode() {
//创建客户端
CuratorFramework client = ClientFactory.createSimple(ZK_ADDRESS);
try {
//启动客户端实例,连接服务器
client.start(); String data = "hello world";
byte[] payload = data.getBytes("UTF-8");
String zkPath = "/test/node-1";
client.setData()
.forPath(zkPath, payload); } catch (Exception e) {
e.printStackTrace();
} finally {
CloseableUtils.closeQuietly(client);
}
}

异步更新,需要用到inBackground()方法,其作用是,让更新操作异步执行。如果需要监听到异步操作的结果,需要为inBackground加上AsyncCallback回调实例。

异步更新的代码如下:

    /**
* 更新节点 - 异步模式
*/
@Test
public void updateNodeAsync() {
//创建客户端
CuratorFramework client = ClientFactory.createSimple(ZK_ADDRESS);
try { //更新完成监听器
AsyncCallback.StringCallback callback = new AsyncCallback.StringCallback() { @Override
public void processResult(int i, String s, Object o, String s1) {
System.out.println(
"i = " + i + " | " +
"s = " + s + " | " +
"o = " + o + " | " +
"s1 = " + s1
);
}
};
//启动客户端实例,连接服务器
client.start(); String data = "hello ,every body! ";
byte[] payload = data.getBytes("UTF-8");
String zkPath = "/test/CRUD/node-1";
client.setData()
.inBackground(callback)
.forPath(zkPath, payload); Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
} finally {
CloseableUtils.closeQuietly(client);
}
}

1.1.6. CRUD 之delete删除节点

删除节点,使用delete 方法,代码如下。

  /**
* 删除节点
*/
@Test
public void deleteNode() {
//创建客户端
CuratorFramework client = ClientFactory.createSimple(ZK_ADDRESS);
try {
//启动客户端实例,连接服务器
client.start(); //删除节点
String zkPath = "/test/CRUD/node-1";
client.delete().forPath(zkPath); //删除后查看结果
String parentPath = "/test";
List<String> children = client.getChildren().forPath(parentPath); for (String child : children) {
log.info("child:", child);
} } catch (Exception e) {
e.printStackTrace();
} finally {
CloseableUtils.closeQuietly(client);
}
}

和更新一样,也可以进行异步删除,同样需要用到inBackground()方法。如果需要监听异步操作的结果,需要为inBackground方法加上一个参数:AsyncCallback回调实例。

写在最后

​ 下一篇:开启zk的客户端开发。


疯狂创客圈 亿级流量 高并发IM 实战 系列

  • Java (Netty) 聊天程序【 亿级流量】实战 开源项目实战


zookeeper curator CRUD的更多相关文章

  1. zookeeper curator客户端之增删改查

    zookeeper curator客户端之增删改查 zookeeper安装:https://www.cnblogs.com/zwcry/p/10272506.html curator客户端是Apach ...

  2. org/apache/curator/RetryPolicy at com.alibaba.dubbo.remoting.zookeeper.curator.CuratorZookeeperTransporter.connect(CuratorZookeeperTransporter.java:26)

    使用dubbo服务,启动项目报错: org/apache/curator/RetryPolicy at com.alibaba.dubbo.remoting.zookeeper.curator.Cur ...

  3. zookeeper curator处理会话过期session expired

    本文介绍在使用curator框架的时候如何handle session expire. 1.什么是zookeeper的会话过期? 一般来说,我们使用zookeeper是集群形式,如下图,client和 ...

  4. zookeeper curator选主(Leader)

    在分布式系统设计中,选主是一个常见的场景.选主是一个这样的过程,通过选主,主节点被选择出来控制其他节点或者是分配任务. 选主算法要满足的几个特征: 1)各个节点均衡的获得成为主节点的权利,一旦主节点被 ...

  5. zookeeper curator使用caches实现各种监听

    1.篇首语 curator是zookeeper的一个高级api开发包.封装了zookeeper众多的recipes,并且实现了一些新的recipes原语,最重要的是基于zookeeper提供的各种机制 ...

  6. springboot使用zookeeper(curator)实现注册发现与负载均衡

    最简单的实现服务高可用的方法就是集群化,也就是分布式部署,但是分布式部署会带来一些问题.比如: 1.各个实例之间的协同(锁) 2.负载均衡 3.热删除 这里通过一个简单的实例来说明如何解决注册发现和负 ...

  7. ZooKeeper基础CRUD操作

    ==============================Curator Java 客户端 CRUD 使用==============================Curator 是 Apache ...

  8. Zookeeper+Curator 分布式锁

    本来想着基于zk临时节点,实现一下分布式锁,结果发现有curator框架.PS:原声API真的难用,连递归创建path都没有? 配置curator maven的时候,md配置了好几个小时,最后发现集中 ...

  9. Zookeeper Curator API 使用

    0. 原生 ZOOKEEPER JAVA API  http://www.cnblogs.com/rocky-fang/p/9030438.html 1. 概述 Curator采用cache封装对事件 ...

随机推荐

  1. [Apollo Server] Get started with Apollo Server

    Get started with apollo server with node.js: Install: npm install --save apollo-server graphql index ...

  2. XP如何在桌面新建宽带连接的快捷方式

    1 打开控制面板,点击网络和Internet连接 2 如果存在宽带连接选项. 则点击左侧的网上邻居,然后点击查看网络连接 右击宽带连接,点击创建快捷方式,放到桌面,改一下快捷方式的名字即可.   3 ...

  3. 如何手动编译运行带包 java 程序

    带包的java程序比普通java程序的编译稍微复杂一些.例如下面的例子: package cn.guopeng; import java.util.*; public class hello { pu ...

  4. python单元测试框架 pyunit

    概况 系统要求 使用PyUnit构建自己的测试 安装 测试用例介绍 创建一个简单测试用例 复用设置代码:创建固件 包含多个测试方法的测试用例类 将测试用例聚合成测试套件 嵌套测试用例 测试代码的放置位 ...

  5. 企业级分布式存储应用与实战MogileFS、FastDFS

    项目实战9—企业级分布式存储应用与实战MogileFS.FastDFS   目录 实战一:企业级分布式存储应用与实战 mogilefs 实现 原理 1.环境准备 2.下载安装,每个机器都一样 3.数据 ...

  6. 正则化--L2正则化

    请查看以下泛化曲线,该曲线显示的是训练集和验证集相对于训练迭代次数的损失. 图 1 显示的是某个模型的训练损失逐渐减少,但验证损失最终增加.换言之,该泛化曲线显示该模型与训练集中的数据过拟合.根据奥卡 ...

  7. 【CODEFORCES】 A. Initial Bet

    A. Initial Bet time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  8. CoreAnimation的使用小结

    參考:http://www.cnblogs.com/wendingding/p/3801157.htmlhttp://www.cnblogs.com/wendingding/p/3802830.htm ...

  9. Atitit.远程接口 监控与木马   常用的api 标准化v2 q216

    Atitit.远程接口 监控与木马   常用的api 标准化v2 q216 1. 木马与远程接口 监控的常用的api2 1.1. 文件复制2 1.2. 屏幕定时截图2 1.3. 邮件发送2 1.4.  ...

  10. Apollo配置中心解惑(一):关于一个portal管理多个环境,要求环境相互之间不影响,独立

    关于作者的回答很官方,不太懂: https://github.com/ctripcorp/apollo/wiki/%E5%88%86%E5%B8%83%E5%BC%8F%E9%83%A8%E7%BD% ...