[转载] 跟着实例学习zookeeper 的用法
原文: http://ifeve.com/zookeeper-curato-framework/
zookeeper 的原生客户端库过于底层, 用户为了使用 zookeeper需要编写大量的代码, 为此Curator框架对 zookeeper 进行了高层次的语义封装, 简化使用 zookeeper 的成本. 只可惜 curator 框架仅仅支持 java 语言, 期待 c++版本出现(或者我们自己尝试实现一个)
跟着实例学习ZooKeeper的用法: Curator框架应用
前面的几篇文章介绍了一些ZooKeeper的应用方法, 本文将介绍Curator访问ZooKeeper的一些基本方法, 而不仅仅限于指定的Recipes, 你可以使用Curator API任意的访问ZooKeeper。
CuratorFramework
Curator框架提供了一套高级的API, 简化了ZooKeeper的操作。 它增加了很多使用ZooKeeper开发的特性,可以处理ZooKeeper集群复杂的连接管理和重试机制。 这些特性包括:
- 自动化的连接管理: 重新建立到ZooKeeper的连接和重试机制存在一些潜在的错误case。 Curator帮助你处理这些事情,对你来说是透明的。
- 清理API:
- 简化了原生的ZooKeeper的方法,事件等
- 提供了一个现代的流式接口
- 提供了Recipes实现: 如前面的文章介绍的那样,基于这些Recipes可以创建很多复杂的分布式应用
Curator框架通过CuratorFrameworkFactory以工厂模式和builder模式创建CuratorFramework实 例。 CuratorFramework实例都是线程安全的,你应该在你的应用中共享同一个CuratorFramework实例.
工厂方法newClient()提供了一个简单方式创建实例。 而Builder提供了更多的参数控制。一旦你创建了一个CuratorFramework实例,你必须调用它的start()启动,在应用退出时调用close()方法关闭.
下面的例子演示了两种创建Curator的方法:
package com.colobu.zkrecipe.framework;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.curator.test.TestingServer;
import org.apache.curator.utils.CloseableUtils;
public class CreateClientExample {
private static final String PATH = "/example/basic";
public static void main(String[] args) throws Exception {
TestingServer server = new TestingServer();
CuratorFramework client = null;
try {
client = createSimple(server.getConnectString());
client.start();
client.create().creatingParentsIfNeeded().forPath(PATH, "test".getBytes());
CloseableUtils.closeQuietly(client);
client = createWithOptions(server.getConnectString(), new ExponentialBackoffRetry(1000, 3), 1000, 1000);
client.start();
System.out.println(new String(client.getData().forPath(PATH)));
} catch (Exception ex) {
ex.printStackTrace();
} finally {
CloseableUtils.closeQuietly(client);
CloseableUtils.closeQuietly(server);
}
}
public static CuratorFramework createSimple(String connectionString) {
// these are reasonable arguments for the ExponentialBackoffRetry.
// The first retry will wait 1 second - the second will wait up to 2 seconds - the
// third will wait up to 4 seconds.
ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(1000, 3);
// The simplest way to get a CuratorFramework instance. This will use default values.
// The only required arguments are the connection string and the retry policy
return CuratorFrameworkFactory.newClient(connectionString, retryPolicy);
}
public static CuratorFramework createWithOptions(String connectionString, RetryPolicy retryPolicy, int connectionTimeoutMs, int sessionTimeoutMs) {
// using the CuratorFrameworkFactory.builder() gives fine grained control
// over creation options. See the CuratorFrameworkFactory.Builder javadoc details
return CuratorFrameworkFactory.builder().connectString(connectionString)
.retryPolicy(retryPolicy)
.connectionTimeoutMs(connectionTimeoutMs)
.sessionTimeoutMs(sessionTimeoutMs)
// etc. etc.
.build();
}
}
Curator框架提供了一种流式接口。 操作通过builder串联起来, 这样方法调用类似语句一样。
client.create().forPath("/head", new byte[0]);
client.delete().inBackground().forPath("/head");
client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/head/child", new byte[0]);
client.getData().watched().inBackground().forPath("/test");
CuratorFramework提供的方法:
方法名 | 描述 |
---|---|
create() | 开始创建操作, 可以调用额外的方法(比如方式mode 或者后台执行background) 并在最后调用forPath()指定要操作的ZNode |
delete() | 开始删除操作. 可以调用额外的方法(版本或者后台处理version or background)并在最后调用forPath()指定要操作的ZNode |
checkExists() | 开始检查ZNode是否存在的操作. 可以调用额外的方法(监控或者后台处理)并在最后调用forPath()指定要操作的ZNode |
getData() | 开始获得ZNode节点数据的操作. 可以调用额外的方法(监控、后台处理或者获取状态watch, background or get stat) 并在最后调用forPath()指定要操作的ZNode |
setData() | 开始设置ZNode节点数据的操作. 可以调用额外的方法(版本或者后台处理) 并在最后调用forPath()指定要操作的ZNode |
getChildren() | 开始获得ZNode的子节点列表。 以调用额外的方法(监控、后台处理或者获取状态watch, background or get stat) 并在最后调用forPath()指定要操作的ZNode |
inTransaction() | 开始是原子ZooKeeper事务. 可以复合create, setData, check, and/or delete 等操作然后调用commit()作为一个原子操作提交 |
后台操作的通知和监控可以通过ClientListener接口发布. 你可以在CuratorFramework实例上通过addListener()
注册listener, Listener实现了下面的方法:
- eventReceived() 一个后台操作完成或者一个监控被触发
事件类型以及事件的方法如下:
Event Type | Event Methods |
---|---|
CREATE | getResultCode() and getPath() |
DELETE | getResultCode() and getPath() |
EXISTS | getResultCode(), getPath() and getStat() |
GETDATA | getResultCode(), getPath(), getStat() and getData() |
SETDATA | getResultCode(), getPath() and getStat() |
CHILDREN | getResultCode(), getPath(), getStat(), getChildren() |
WATCHED | getWatchedEvent() |
还可以通过ConnectionStateListener
接口监控连接的状态。 强烈推荐你增加这个监控器。
你可以使用命名空间Namespace避免多个应用的节点的名称冲突。 CuratorFramework提供了命名空间的概念,这样CuratorFramework会为它的API调用的path加上命名空间:
CuratorFramework client = CuratorFrameworkFactory.builder().namespace("MyApp") ... build();
...
client.create().forPath("/test", data);
// node was actually written to: "/MyApp/test"
Curator还提供了临时的CuratorFramework: CuratorTempFramework
, 一定时间不活动后连接会被关闭。这hi基于Camille Fournier的一篇文章: http://whilefalse.blogspot.com/2012/12/building-global-highly-available.html.
创建builder时不是调用build()
而是调用buildTemp()
。 3分钟不活动连接就被关闭,你也可以指定不活动的时间。 它只提供了下面几个方法:
public void close();
public CuratorTransaction inTransaction() throws Exception;
public TempGetDataBuilder getData() throws Exception;
操作方法
上面的表格列出了CuratorFramework可以用的操作。 下面就是一个例子:
package com.colobu.zkrecipe.framework;
import java.util.List;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.BackgroundCallback;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.api.CuratorListener;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.Watcher;
public class CrudExample {
public static void main(String[] args) {
}
public static void create(CuratorFramework client, String path, byte[] payload) throws Exception {
// this will create the given ZNode with the given data
client.create().forPath(path, payload);
}
public static void createEphemeral(CuratorFramework client, String path, byte[] payload) throws Exception {
// this will create the given EPHEMERAL ZNode with the given data
client.create().withMode(CreateMode.EPHEMERAL).forPath(path, payload);
}
public static String createEphemeralSequential(CuratorFramework client, String path, byte[] payload) throws Exception {
// this will create the given EPHEMERAL-SEQUENTIAL ZNode with the given
// data using Curator protection.
return client.create().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path, payload);
}
public static void setData(CuratorFramework client, String path, byte[] payload) throws Exception {
// set data for the given node
client.setData().forPath(path, payload);
}
public static void setDataAsync(CuratorFramework client, String path, byte[] payload) throws Exception {
// this is one method of getting event/async notifications
CuratorListener listener = new CuratorListener() {
@Override
public void eventReceived(CuratorFramework client, CuratorEvent event) throws Exception {
// examine event for details
}
};
client.getCuratorListenable().addListener(listener);
// set data for the given node asynchronously. The completion
// notification
// is done via the CuratorListener.
client.setData().inBackground().forPath(path, payload);
}
public static void setDataAsyncWithCallback(CuratorFramework client, BackgroundCallback callback, String path, byte[] payload) throws Exception {
// this is another method of getting notification of an async completion
client.setData().inBackground(callback).forPath(path, payload);
}
public static void delete(CuratorFramework client, String path) throws Exception {
// delete the given node
client.delete().forPath(path);
}
public static void guaranteedDelete(CuratorFramework client, String path) throws Exception {
// delete the given node and guarantee that it completes
client.delete().guaranteed().forPath(path);
}
public static List<String> watchedGetChildren(CuratorFramework client, String path) throws Exception {
/**
* Get children and set a watcher on the node. The watcher notification
* will come through the CuratorListener (see setDataAsync() above).
*/
return client.getChildren().watched().forPath(path);
}
public static List<String> watchedGetChildren(CuratorFramework client, String path, Watcher watcher) throws Exception {
/**
* Get children and set the given watcher on the node.
*/
return client.getChildren().usingWatcher(watcher).forPath(path);
}
}
事务
上面也提到, CuratorFramework提供了事务的概念,可以将一组操作放在一个原子事务中。 什么叫事务? 事务是原子的, 一组操作要么都成功,要么都失败。
下面的例子演示了事务的操作:
package com.colobu.zkrecipe.framework;
import java.util.Collection;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.transaction.CuratorTransaction;
import org.apache.curator.framework.api.transaction.CuratorTransactionFinal;
import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
public class TransactionExample {
public static void main(String[] args) {
}
public static Collection<CuratorTransactionResult> transaction(CuratorFramework client) throws Exception {
// this example shows how to use ZooKeeper's new transactions
Collection<CuratorTransactionResult> results = client.inTransaction().create().forPath("/a/path", "some data".getBytes())
.and().setData().forPath("/another/path", "other data".getBytes())
.and().delete().forPath("/yet/another/path")
.and().commit(); // IMPORTANT!
// called
for (CuratorTransactionResult result : results) {
System.out.println(result.getForPath() + " - " + result.getType());
}
return results;
}
/*
* These next four methods show how to use Curator's transaction APIs in a
* more traditional - one-at-a-time - manner
*/
public static CuratorTransaction startTransaction(CuratorFramework client) {
// start the transaction builder
return client.inTransaction();
}
public static CuratorTransactionFinal addCreateToTransaction(CuratorTransaction transaction) throws Exception {
// add a create operation
return transaction.create().forPath("/a/path", "some data".getBytes()).and();
}
public static CuratorTransactionFinal addDeleteToTransaction(CuratorTransaction transaction) throws Exception {
// add a delete operation
return transaction.delete().forPath("/another/path").and();
}
public static void commitTransaction(CuratorTransactionFinal transaction) throws Exception {
// commit the transaction
transaction.commit();
}
}
原创文章,转载请注明: 转载自并发编程网 – ifeve.com
本文链接地址: 跟着实例学习ZooKeeper的用法: Curator框架应用
[转载] 跟着实例学习zookeeper 的用法的更多相关文章
- 跟着实例学习ZooKeeper的用法: 分布式锁
锁 分布式的锁全局同步, 这意味着任何一个时间点不会有两个客户端都拥有相同的锁. 可重入锁Shared Reentrant Lock 首先我们先看一个全局可重入的锁. Shared意味着锁是全局可见的 ...
- [转载]PyTorch中permute的用法
[转载]PyTorch中permute的用法 来源:https://blog.csdn.net/york1996/article/details/81876886 permute(dims) 将ten ...
- 转载:Hadoop排序工具用法小结
本文转载自Silhouette的文章,原文地址:http://www.dreamingfish123.info/?p=1102 Hadoop排序工具用法小结 发表于 2014 年 8 月 25 日 由 ...
- 【转载】python super的用法
转载地址: http://blog.csdn.net/cxm19830125/article/details/20610533 super的用法是调用继承类的初始化方法,如下面的代码: class A ...
- 【转载】extern "C"的用法解析(原博主就是抄百度百科的,不如另外一篇好)
[说明]文章转载自Rollen Holt 的文章 http://www.cnblogs.com/rollenholt/archive/2012/03/20/2409046.html --------- ...
- (转载)mysql group by 用法解析(详细)
(转载)http://blog.tianya.cn/blogger/post_read.asp?BlogID=4221189&PostID=47881614 mysql distinct 去重 ...
- (转载)mysql中limit用法
(转载)http://hi.baidu.com/sppeivan/item/e45179375d6778c62f8ec221 mysql中limit用法 使用查询语句的时候,经常要返回前几条或者中 ...
- 转载:深入浅出Zookeeper
ZAB协议 ZAB协议是专门为zookeeper实现分布式协调功能而设计.zookeeper主要是根据ZAB协议是实现分布式系统数据一致性. zookeeper根据ZAB协议建立了主备模型完成zook ...
- 转载:深入浅出Zookeeper(一) Zookeeper架构及FastLeaderElection机制
转载至 http://www.jasongj.com/zookeeper/fastleaderelection/: 原创文章,转载请务必将下面这段话置于文章开头处.本文转发自技术世界,原文链接 htt ...
随机推荐
- ThinkPHP跳转与重定向的区别在哪里
跳转: 浏览器认为 : 当前 URL 请求成功 , 重新请求新的 URL . 浏览器会记录当前的 URL 和新的 URL 在请求历史记录中. 回退, 是可以回退到 , 当前的 URL 上的 . ( 无 ...
- iOS开发必备HUD(透明指示层)
iOS开发必备HUD(透明指示层) 字数421 阅读2123 评论1 喜欢51 1.MBProgressHUD GitHub地址:https://github.com/jdg/MBProgressHU ...
- win2003 服务器安全设置详细介绍
第一步:一.先关闭不需要的端口 我比较小心,先关了端口.只开了3389 21 80 1433(MYSQL)有些人一直说什么默认的3389不安全,对此我不否认,但是利用的途径也只能一个一个的穷举爆破, ...
- oracle 树状查询
做树状查询的时候,oracle有自己的优势,一条sql语句就可以搞定,而mysql这种数据库就只能用递归了... 递归的项目实例: //递归取到栏目路径 public List getTreeList ...
- SQL数据类型大全 《转自网络》
数据类型是数据的一种属性,表示数据所表示信息的类型.任何一种计算机语言都定义了自己的数据类型.当然,不同的程序语言都具有不同的特点,所定义的数据类型的种类和名称都或多或少有些不同.SQLServer ...
- LINQ TO DATATABLE/DATASET基本操作之-简单查询
废话不说,直接贴上代码: 其中:SerchLinqData();方法查询数据并返回一个datatable表.为数据源. #region 绑定数据 public static string BindDt ...
- 2016年12月9日 星期五 --出埃及记 Exodus 21:4
2016年12月9日 星期五 --出埃及记 Exodus 21:4 If his master gives him a wife and she bears him sons or daughters ...
- 常用PDF文档开发库
C++库: 1,PDF类库 PoDoFo http://podofo.sourceforge.net/ PoDoFo 是一个用来操作 PDF 文件格式的 C++ 类库.它还包含一些小工具用来解析 ...
- RabbitMQ术语
工作队列:Working Queue 分配:多个客户端接收同一个Queue,如何做负载均衡(分配). Round-robin分配:多个接收端接收同一个Queue时,采用了Round-robin ...
- django cycle标签
django 模板系统 有很多标签,其中cycle我觉得不好理解,至少网上文档也不好理解. 这些标签可以通过渲染模板文件而获得我们预期的效果和文字,常用的有如下这些标签: 标签:{% 标签名 %}{% ...