原文: 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 的用法的更多相关文章

  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. ThinkPHP跳转与重定向的区别在哪里

    跳转: 浏览器认为 : 当前 URL 请求成功 , 重新请求新的 URL . 浏览器会记录当前的 URL 和新的 URL 在请求历史记录中. 回退, 是可以回退到 , 当前的 URL 上的 . ( 无 ...

  2. iOS开发必备HUD(透明指示层)

    iOS开发必备HUD(透明指示层) 字数421 阅读2123 评论1 喜欢51 1.MBProgressHUD GitHub地址:https://github.com/jdg/MBProgressHU ...

  3. win2003 服务器安全设置详细介绍

    第一步:一.先关闭不需要的端口  我比较小心,先关了端口.只开了3389 21 80 1433(MYSQL)有些人一直说什么默认的3389不安全,对此我不否认,但是利用的途径也只能一个一个的穷举爆破, ...

  4. oracle 树状查询

    做树状查询的时候,oracle有自己的优势,一条sql语句就可以搞定,而mysql这种数据库就只能用递归了... 递归的项目实例: //递归取到栏目路径 public List getTreeList ...

  5. SQL数据类型大全 《转自网络》

    数据类型是数据的一种属性,表示数据所表示信息的类型.任何一种计算机语言都定义了自己的数据类型.当然,不同的程序语言都具有不同的特点,所定义的数据类型的种类和名称都或多或少有些不同.SQLServer ...

  6. LINQ TO DATATABLE/DATASET基本操作之-简单查询

    废话不说,直接贴上代码: 其中:SerchLinqData();方法查询数据并返回一个datatable表.为数据源. #region 绑定数据 public static string BindDt ...

  7. 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 ...

  8. 常用PDF文档开发库

    C++库: 1,PDF类库 PoDoFo   http://podofo.sourceforge.net/  PoDoFo 是一个用来操作 PDF 文件格式的 C++ 类库.它还包含一些小工具用来解析 ...

  9. RabbitMQ术语

    工作队列:Working Queue 分配:多个客户端接收同一个Queue,如何做负载均衡(分配).     Round-robin分配:多个接收端接收同一个Queue时,采用了Round-robin ...

  10. django cycle标签

    django 模板系统 有很多标签,其中cycle我觉得不好理解,至少网上文档也不好理解. 这些标签可以通过渲染模板文件而获得我们预期的效果和文字,常用的有如下这些标签: 标签:{% 标签名 %}{% ...