原文: 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的方法:

  1. package com.colobu.zkrecipe.framework;
  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.curator.test.TestingServer;
  7. import org.apache.curator.utils.CloseableUtils;
  8. public class CreateClientExample {
  9. private static final String PATH = "/example/basic";
  10. public static void main(String[] args) throws Exception {
  11. TestingServer server = new TestingServer();
  12. CuratorFramework client = null;
  13. try {
  14. client = createSimple(server.getConnectString());
  15. client.start();
  16. client.create().creatingParentsIfNeeded().forPath(PATH, "test".getBytes());
  17. CloseableUtils.closeQuietly(client);
  18. client = createWithOptions(server.getConnectString(), new ExponentialBackoffRetry(1000, 3), 1000, 1000);
  19. client.start();
  20. System.out.println(new String(client.getData().forPath(PATH)));
  21. } catch (Exception ex) {
  22. ex.printStackTrace();
  23. } finally {
  24. CloseableUtils.closeQuietly(client);
  25. CloseableUtils.closeQuietly(server);
  26. }
  27. }
  28. public static CuratorFramework createSimple(String connectionString) {
  29. // these are reasonable arguments for the ExponentialBackoffRetry.
  30. // The first retry will wait 1 second - the second will wait up to 2 seconds - the
  31. // third will wait up to 4 seconds.
  32. ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(1000, 3);
  33. // The simplest way to get a CuratorFramework instance. This will use default values.
  34. // The only required arguments are the connection string and the retry policy
  35. return CuratorFrameworkFactory.newClient(connectionString, retryPolicy);
  36. }
  37. public static CuratorFramework createWithOptions(String connectionString, RetryPolicy retryPolicy, int connectionTimeoutMs, int sessionTimeoutMs) {
  38. // using the CuratorFrameworkFactory.builder() gives fine grained control
  39. // over creation options. See the CuratorFrameworkFactory.Builder javadoc details
  40. return CuratorFrameworkFactory.builder().connectString(connectionString)
  41. .retryPolicy(retryPolicy)
  42. .connectionTimeoutMs(connectionTimeoutMs)
  43. .sessionTimeoutMs(sessionTimeoutMs)
  44. // etc. etc.
  45. .build();
  46. }
  47. }

Curator框架提供了一种流式接口。 操作通过builder串联起来, 这样方法调用类似语句一样。

  1. client.create().forPath("/head", new byte[0]);
  2. client.delete().inBackground().forPath("/head");
  3. client.create().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/head/child", new byte[0]);
  4. 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加上命名空间:

  1. CuratorFramework client = CuratorFrameworkFactory.builder().namespace("MyApp") ... build();
  2. ...
  3. client.create().forPath("/test", data);
  4. // 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分钟不活动连接就被关闭,你也可以指定不活动的时间。 它只提供了下面几个方法:

  1. public void close();
  2. public CuratorTransaction inTransaction() throws Exception;
  3. public TempGetDataBuilder getData() throws Exception;

操作方法

上面的表格列出了CuratorFramework可以用的操作。 下面就是一个例子:

  1. package com.colobu.zkrecipe.framework;
  2. import java.util.List;
  3. import org.apache.curator.framework.CuratorFramework;
  4. import org.apache.curator.framework.api.BackgroundCallback;
  5. import org.apache.curator.framework.api.CuratorEvent;
  6. import org.apache.curator.framework.api.CuratorListener;
  7. import org.apache.zookeeper.CreateMode;
  8. import org.apache.zookeeper.Watcher;
  9. public class CrudExample {
  10. public static void main(String[] args) {
  11. }
  12. public static void create(CuratorFramework client, String path, byte[] payload) throws Exception {
  13. // this will create the given ZNode with the given data
  14. client.create().forPath(path, payload);
  15. }
  16. public static void createEphemeral(CuratorFramework client, String path, byte[] payload) throws Exception {
  17. // this will create the given EPHEMERAL ZNode with the given data
  18. client.create().withMode(CreateMode.EPHEMERAL).forPath(path, payload);
  19. }
  20. public static String createEphemeralSequential(CuratorFramework client, String path, byte[] payload) throws Exception {
  21. // this will create the given EPHEMERAL-SEQUENTIAL ZNode with the given
  22. // data using Curator protection.
  23. return client.create().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path, payload);
  24. }
  25. public static void setData(CuratorFramework client, String path, byte[] payload) throws Exception {
  26. // set data for the given node
  27. client.setData().forPath(path, payload);
  28. }
  29. public static void setDataAsync(CuratorFramework client, String path, byte[] payload) throws Exception {
  30. // this is one method of getting event/async notifications
  31. CuratorListener listener = new CuratorListener() {
  32. @Override
  33. public void eventReceived(CuratorFramework client, CuratorEvent event) throws Exception {
  34. // examine event for details
  35. }
  36. };
  37. client.getCuratorListenable().addListener(listener);
  38. // set data for the given node asynchronously. The completion
  39. // notification
  40. // is done via the CuratorListener.
  41. client.setData().inBackground().forPath(path, payload);
  42. }
  43. public static void setDataAsyncWithCallback(CuratorFramework client, BackgroundCallback callback, String path, byte[] payload) throws Exception {
  44. // this is another method of getting notification of an async completion
  45. client.setData().inBackground(callback).forPath(path, payload);
  46. }
  47. public static void delete(CuratorFramework client, String path) throws Exception {
  48. // delete the given node
  49. client.delete().forPath(path);
  50. }
  51. public static void guaranteedDelete(CuratorFramework client, String path) throws Exception {
  52. // delete the given node and guarantee that it completes
  53. client.delete().guaranteed().forPath(path);
  54. }
  55. public static List<String> watchedGetChildren(CuratorFramework client, String path) throws Exception {
  56. /**
  57. * Get children and set a watcher on the node. The watcher notification
  58. * will come through the CuratorListener (see setDataAsync() above).
  59. */
  60. return client.getChildren().watched().forPath(path);
  61. }
  62. public static List<String> watchedGetChildren(CuratorFramework client, String path, Watcher watcher) throws Exception {
  63. /**
  64. * Get children and set the given watcher on the node.
  65. */
  66. return client.getChildren().usingWatcher(watcher).forPath(path);
  67. }
  68. }

事务

上面也提到, CuratorFramework提供了事务的概念,可以将一组操作放在一个原子事务中。 什么叫事务? 事务是原子的, 一组操作要么都成功,要么都失败。

下面的例子演示了事务的操作:

  1. package com.colobu.zkrecipe.framework;
  2. import java.util.Collection;
  3. import org.apache.curator.framework.CuratorFramework;
  4. import org.apache.curator.framework.api.transaction.CuratorTransaction;
  5. import org.apache.curator.framework.api.transaction.CuratorTransactionFinal;
  6. import org.apache.curator.framework.api.transaction.CuratorTransactionResult;
  7. public class TransactionExample {
  8. public static void main(String[] args) {
  9. }
  10. public static Collection<CuratorTransactionResult> transaction(CuratorFramework client) throws Exception {
  11. // this example shows how to use ZooKeeper's new transactions
  12. Collection<CuratorTransactionResult> results = client.inTransaction().create().forPath("/a/path", "some data".getBytes())
  13. .and().setData().forPath("/another/path", "other data".getBytes())
  14. .and().delete().forPath("/yet/another/path")
  15. .and().commit(); // IMPORTANT!
  16. // called
  17. for (CuratorTransactionResult result : results) {
  18. System.out.println(result.getForPath() + " - " + result.getType());
  19. }
  20. return results;
  21. }
  22. /*
  23. * These next four methods show how to use Curator's transaction APIs in a
  24. * more traditional - one-at-a-time - manner
  25. */
  26. public static CuratorTransaction startTransaction(CuratorFramework client) {
  27. // start the transaction builder
  28. return client.inTransaction();
  29. }
  30. public static CuratorTransactionFinal addCreateToTransaction(CuratorTransaction transaction) throws Exception {
  31. // add a create operation
  32. return transaction.create().forPath("/a/path", "some data".getBytes()).and();
  33. }
  34. public static CuratorTransactionFinal addDeleteToTransaction(CuratorTransaction transaction) throws Exception {
  35. // add a delete operation
  36. return transaction.delete().forPath("/another/path").and();
  37. }
  38. public static void commitTransaction(CuratorTransactionFinal transaction) throws Exception {
  39. // commit the transaction
  40. transaction.commit();
  41. }
  42. }

原创文章,转载请注明: 转载自并发编程网 – ifeve.com

本文链接地址: 跟着实例学习ZooKeeper的用法: Curator框架应用

 
 

[转载] 跟着实例学习zookeeper 的用法的更多相关文章

  1. 跟着实例学习ZooKeeper的用法: 分布式锁

    锁 分布式的锁全局同步, 这意味着任何一个时间点不会有两个客户端都拥有相同的锁. 可重入锁Shared Reentrant Lock 首先我们先看一个全局可重入的锁. Shared意味着锁是全局可见的 ...

  2. [转载]PyTorch中permute的用法

    [转载]PyTorch中permute的用法 来源:https://blog.csdn.net/york1996/article/details/81876886 permute(dims) 将ten ...

  3. 转载:Hadoop排序工具用法小结

    本文转载自Silhouette的文章,原文地址:http://www.dreamingfish123.info/?p=1102 Hadoop排序工具用法小结 发表于 2014 年 8 月 25 日 由 ...

  4. 【转载】python super的用法

    转载地址: http://blog.csdn.net/cxm19830125/article/details/20610533 super的用法是调用继承类的初始化方法,如下面的代码: class A ...

  5. 【转载】extern "C"的用法解析(原博主就是抄百度百科的,不如另外一篇好)

    [说明]文章转载自Rollen Holt 的文章 http://www.cnblogs.com/rollenholt/archive/2012/03/20/2409046.html --------- ...

  6. (转载)mysql group by 用法解析(详细)

    (转载)http://blog.tianya.cn/blogger/post_read.asp?BlogID=4221189&PostID=47881614 mysql distinct 去重 ...

  7. (转载)mysql中limit用法

    (转载)http://hi.baidu.com/sppeivan/item/e45179375d6778c62f8ec221   mysql中limit用法 使用查询语句的时候,经常要返回前几条或者中 ...

  8. 转载:深入浅出Zookeeper

    ZAB协议 ZAB协议是专门为zookeeper实现分布式协调功能而设计.zookeeper主要是根据ZAB协议是实现分布式系统数据一致性. zookeeper根据ZAB协议建立了主备模型完成zook ...

  9. 转载:深入浅出Zookeeper(一) Zookeeper架构及FastLeaderElection机制

    转载至 http://www.jasongj.com/zookeeper/fastleaderelection/: 原创文章,转载请务必将下面这段话置于文章开头处.本文转发自技术世界,原文链接 htt ...

随机推荐

  1. 在Linux下搭建Git服务器的方法是什么样?

    第一步 安装git:可以通过命令的方式快速安装,不同的linux的安装方法可能不一样,我的是采用的yum方法.ubuntu可以用apt-get命令.sudo yum install git 第二步 添 ...

  2. 本人整理的一些PHP常用函数

    <?php //===============================时间日期=============================== //y返回年最后两位,Y年四位数,m月份数字 ...

  3. ecshop微信支付(0923更新)商户支付密钥key的生成与设置

    ECSHOP 微信支付(0923更新)商户支付密钥key的生成与设置 说明:新版微信支付,用户必须授权登录才能支付.需要商家自己设置商户号支付密钥. 申请微信支付手机版部分时需要填写的配置接口地址: ...

  4. [thml]HTML select标签 获取选中的option的value及Text内容

    很简单的select标签: <select id="hello" onchange="getContent(this.value,this.options[this ...

  5. ACM题目————STL练习之 懒省事的小明(优先队列)

    描述 小明很想吃果子,正好果园果子熟了.在果园里,小明已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.小明决定把所有的果子合成一堆. 因为小明比较懒,为了省力气,小明开始想点子了: 每一 ...

  6. c语言中各个类型的sizeof长度

    #include <stdio.h> int main() {     printf("\nA Char is %lu bytes", sizeof( char )); ...

  7. CountDownLatch的原理学习

    转载:http://blog.csdn.net/yanyan19880509/article/details/52349056 前言 前面介绍了ReentrantLock,又叫排他锁,本篇主要通过Co ...

  8. easyUI的window包含一个iframe,在iframe中如何关闭window?

    easyUI的window包含一个iframe,在iframe中如何关闭window? parent.$('#win').window('close');

  9. hdu 3398

    String Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  10. VC 实现文件与应用程序关联(转载)

    转载:http://www.cnblogs.com/RascallySnake/archive/2013/03/01/2939102.html 日常工作中,doc文件直接双击后,就能启动word软件, ...