03.Curator深入使用

1.Apache Curator简介

Curator提供了一套Java类库,可以更容易的使用ZooKeeper。ZooKeeper本身提供了Java Client的访问类,但是API太底层,不宜使用,易出错。Curator提供了三个组件。Curator client用来替代ZOoKeeper提供的类,它封装了底层的管理并提供了一些有用的工具。Curator framework提供了高级的API来简化ZooKeeper的使用。它增加了很多基于ZooKeeper的特性,帮助管理ZooKeeper的连接以及重试操作。Curator Recipes提供了使用ZooKeeper的一些通用的技巧(方法)。除此之外,Curator Test提供了基于ZooKeeper的单元测试工具。

所谓技巧(Recipes),也可以称之为解决方案,或者叫实现方案,是指ZooKeeper的使用方法,比如分布式的配置管理,Leader选举等。

Curator最初由Netflix的Jordan Zimmerman开发。20117月在github上基于Apache 2.0开源协议开源。之后发布了多个版本,并被广泛的应用。Curator作为Apache ZooKeeper天生配套的组件。ZooKeeper的Java开发者自然而然的会选择它在项目中使用。

1.Curator组件概览

  • Recipes:通用ZooKeeper技巧("recipes")的实现. 建立在Curator Framework之上
  • Framework:简化zookeeper使用的高级. 增加了很多建立在zooper之上的特性. 管理复杂连接处理和重试操作
  • Utilities:各种工具类
  • Client:ZooKeeper本身提供的类的替代者。负责底层的开销以及一些工具
  • Errors:Curator怎样来处理错误和异常
  • Extensions:curator-recipes包实现了通用的技巧,这些技巧在ZooKeeper文档中有介绍。为了避免是这个包(package)变得巨大,recipes/applications将会放入一个独立的extension包下。并使用命名规则curator-x-name

2.Maven/Artifacts

Curator编译好的类库被发布到Maven Center中。Curator包含几个artifact. 你可以根据你的需要在你的项目中加入相应的依赖。对于大多数开发者来说,引入curator-recipes这一个就足够了。

  1. <dependency>
  2. <groupId>org.apache.curator</groupId>
  3. <artifactId>curator-client</artifactId>
  4. <version>2.9.0</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.apache.curator</groupId>
  8. <artifactId>curator-framework</artifactId>
  9. <version>2.9.0</version>
  10. </dependency>
  11. <dependency>
  12. <groupId>org.apache.curator</groupId>
  13. <artifactId>curator-recipes</artifactId>
  14. <version>2.9.0</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.apache.curator</groupId>
  18. <artifactId>curator-x-discovery</artifactId>
  19. <version>2.9.0</version>
  20. </dependency>
  21. <dependency>
  22. <groupId>org.apache.curator</groupId>
  23. <artifactId>curator-examples</artifactId>
  24. <version>2.9.0</version>
  25. </dependency>

2.Apache Curator Recipes

Curator实现了 ZooKeeper recipes文档中列出的所有技巧(除了两段提交two phase commit)。下面介绍Recipes的使用,参考官网:http://curator.apache.org/curator-recipes/index.html

1.Elections(选举)

  • Leader Latch - 在分布式计算中,leader选举是在几台节点中指派单一的进程作为任务组织者的过程。在任务开始前, 所有的网络节点都不知道哪一个节点会作为任务的leader或coordinator. 一旦leader选举算法被执行, 网络中的每个节点都将知道一个特别的唯一的节点作为任务leader
  • Leader Election - 初始的leader选举实现

2.Locks(锁)

  • Shared Reentrant Lock - 全功能的分布式锁。任何一刻不会有两个client同时拥有锁
  • Shared Lock - 与Shared Reentrant Lock类似但是不是重入的
  • Shared Reentrant Read Write Lock - 类似Java的读写锁,但是是分布式的
  • Shared Semaphore - 跨JVM的计数信号量
  • Multi Shared Lock - 将多个锁看成整体,要不全部acquire成功,要不acquire全部失败。release也是释放全部锁

3.Barriers(障碍)

  • Barrier - 分布式的barriers。会阻塞全部的节点的处理,直到条件满足,所有的节点会继续执行
  • Double Barrier - 双barrier允许客户端在一个计算开始点和结束点保持同步。当足够的进程加入barrier,进程开始它们的计算,当所有的进程完成计算才离开

4.Counters(计数器)

  • Shared Counter - 管理一个共享的整数integer.所有监控同一path的客户端都会得到最新的值(ZK的一致性保证)
  • Distributed Atomic Long - 尝试原子增加的计数器首先它尝试乐观锁.如果失败,可选的InterProcessMutex会被采用.不管是optimistic 还是 mutex,重试机制都被用来尝试增加值

5.Caches(缓存)

  • Path Cache - Path Cache是用来监控子节点的。每当一个子节点“曾加、更新或删除”,将会触发事件,事件就是注册了的PathChildrenCacheListener实例执行。Path Cache的功能主要由PathChildrenCache类提供。
  • Node Cache - 用于监控节点,当节点数据被修改或节点被删除,就会触发事件,事件就是注册了的NodeCacheListener实例执行。Node Cache的功能主要由NodeCache类提供。

6.Nodes(节点)

  • Persistent Ephemeral Node - 临时节点,可以通过连接或会话中断一个临时节点。

7.Queues(队列)

  • Distributed Queue - 分布式的ZK队列
  • Distributed Id Queue - 分布式的ZK队列,它支持分配ID来添加到队列中的项目的替换版本
  • Distributed Priority Queue - 分布式优先级的ZK队列
  • Distributed Delay Queue - 分布式的延迟ZK队列
  • Simple Distributed Queue - 一个简单的替代自带的ZK分布式队列(Distributed Queue)

其具体的实现示例,可参考官网:http://curator.apache.org/curator-recipes/index.html

3.Apache Curator Framework

Curator framework提供了高级API, 极大的简化了ZooKeeper的使用。 它在ZooKeeper基础上增加了很多特性,可以管理与ZOoKeeper的连接和重试机制。这些特性包括:

  • 自动连接管理:有些潜在的错误情况需要让ZooKeeper client重建连接和重试。Curator可以自动地和透明地处理这些情况
  • Cleaner API:简化原始的ZooKeeper方法,事件等 提供现代的流式接口

1.产生Curator framework实例

使用CuratorFrameworkFactory产生framework实例。 CuratorFrameworkFactory 既提供了factory方法也提供了builder来创建实例。CuratorFrameworkFactory是线程安全的。你应该在应用中为单一的ZooKeeper集群共享唯一的CuratorFramework实例。

工厂方法(newClient())提供了一个简单的方式创建实例。Builder可以使用更多的参数控制生成的实例。一旦生成framework实例, 必须调用start方法启动它。应用结束时应该调用close方法关闭它。

2.CuratorFramework API

CuratorFramework 使用流程风格的接口。 代码胜于说教:

  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()作为一个原子操作提交

3.通知 Notifications

服务于后台操作和监控(watch)的通知通过ClientListener接口发布。你通过CuratorFramework实例的addListener方法可以注册监听器。

其事件触发时间说明:

  • CuratorListenable:当使用后台线程操作时,后台线程执行完成就会触发,例如:client.getData().inBackground().forPath("/test");后台获取节点数据,获取完成之后触发。
  • ConnectionStateListenable:当连接状态变化时触发。
  • UnhandledErrorListenable:当后台操作发生异常时触发。

CuratorListenable事件触发返回的数据如下:


事件类型        事件返回数据

CREATE          getResultCode() and getPath()

DELETE          getResultCode() and getPath()

EXISTS          getResultCode(), getPath() and getStat()

GET_DATA        getResultCode(), getPath(), getStat() and getData()

SET_DATA        getResultCode(), getPath() and getStat()

CHILDREN        getResultCode(), getPath(), getStat(), getChildren()

SYNC            getResultCode(), getStat()

GET_ACL         getResultCode(), getACLList()

SET_ACL         getResultCode()

TRANSACTION     getResultCode(), getOpResults()

WATCHED         getWatchedEvent()

GET_CONFIG      getResultCode(), getData()

RECONFIG        getResultCode(), getData()

4.命名空间

你可以使用命名空间Namespace避免多个应用的节点的名称冲突。 CuratorFramework提供了命名空间的概念,这样CuratorFramework会为它的API调用的path加上命名空间:


CuratorFramework client = CuratorFrameworkFactory.builder().namespace("MyApp") ... build();

5.临时客户端

Curator还提供了临时的CuratorFramework:CuratorTempFramework,一定时间不活动后连接会被关闭。创建builder时不是调用build()而是调用buildTemp()。3分钟不活动连接就被关闭,你也可以指定不活动的时间。


CuratorTempFramework client = CuratorFrameworkFactory.builder()

    .connectString("127.0.0.1:2181")// 连接串

    .retryPolicy(new RetryNTimes(10, 5000))// 重试策略

    .connectionTimeoutMs(100) // 连接超时

    .sessionTimeoutMs(100) // 会话超时

    .buildTemp(100, TimeUnit.MINUTES); // 临时客户端并设置连接时间

它只提供了下面几个方法:


public void     close();

public CuratorTransaction inTransaction() throws Exception;

public TempGetDataBuilder getData() throws Exception;

6.Retry策略

retry策略可以改变retry的行为。 它抽象出RetryPolicy接口, 包含一个方法public boolean allowRetry(int retryCount, long elapsedTimeMs);。 在retry被尝试执行前, allowRetry()被调用,并且将当前的重试次数和操作已用时间作为参数. 如果返回true, retry被执行。否则异常被抛出。

Curator本身提供了几个策略:

  • ExponentialBackoffRetry:重试一定次数,每次重试sleep更多的时间
  • RetryNTimes:重试N次
  • RetryOneTime:重试一次
  • RetryUntilElapsed:重试一定的时间

4.Apache Curator Utilities

Curator提供了一组工具类和方法用来测试基于Curator的应用。 并且提供了操作ZNode辅助类以及其它一些数据结构

1.Test Server

curator-test提供了TestingServer类。 这个类创建了一个本地的, 同进程的ZooKeeper服务器用来测试。

  1. public static void main(String[] args) throws Exception
  2. {
  3. TestingServer server = new TestingServer();
  4. CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new ExponentialBackoffRetry(1000, 3));
  5. client.getConnectionStateListenable().addListener(new ConnectionStateListener()
  6. {
  7. @Override
  8. public void stateChanged(CuratorFramework client, ConnectionState newState)
  9. {
  10. System.out.println("连接状态:" + newState.name());
  11. }
  12. });
  13. client.start();
  14. System.out.println(client.getChildren().forPath("/"));
  15. client.create().forPath("/test");
  16. System.out.println(client.getChildren().forPath("/"));
  17. CloseableUtils.closeQuietly(client);
  18. CloseableUtils.closeQuietly(server);
  19. System.out.println("OK!");
  20. }

2.Test Cluster

curator-test提供了TestingCluster类。 这个类创建了一个内部的ZooKeeper集群用来测试。

  1. public static void main(String[] args) throws Exception
  2. {
  3. TestingCluster cluster = new TestingCluster(3);
  4. cluster.start();
  5. for (TestingZooKeeperServer server : cluster.getServers())
  6. {
  7. System.out.println(server.getInstanceSpec());
  8. }
  9. cluster.stop();
  10. CloseableUtils.closeQuietly(cluster);
  11. System.out.println("OK!");
  12. }

3.ZKPaths

提供了各种静态方法来操作ZNode:

  • getNodeFromPath: 从一个全路径中得到节点名, 比如 "/one/two/three" 返回 "three"
  • mkdirs: 确保所有的节点都已被创建
  • getSortedChildren: 得到一个给定路径的子节点, 按照sequence number排序
  • makePath: 给定父路径和子节点,创建一个全路径

4.EnsurePath

确保一个特定的路径被创建。当它第一次使用时,一个同步ZKPaths.mkdirs(ZooKeeper, String)调用被触发来确保完整的路径都已经被创建。后续的调用将不是同步操作.用法:

  1. EnsurePath ensurePath = new EnsurePath(aFullPathToEnsure);
  2. ...
  3. String nodePath = aFullPathToEnsure + "/foo";
  4. ensurePath.ensure(zk); // first time syncs and creates if needed
  5. zk.create(nodePath, ...);
  6. ...
  7. ensurePath.ensure(zk); // subsequent times are NOPs
  8. zk.create(nodePath, ...);

注意: 此方法namespace会参与路径名字的创建。

5.Blocking Queue Consumer(阻塞队列消费者)

请参看Distributed Queue 和 Distributed Priority Queue。提供JDK BlockingQueue类似的行为。

6.Queue Sharder

由于zookeeper传输层的限制,单一的队列如果超过10K的元素会被分割(break)。这个类为多个分布式队列提供了一个facade。它监控队列,如果一个队列超过这个阈值,一个新的队列就被创建。在这些队列中Put是分布式的。

7.Reaper and ChildReaper

Reaper

可以用来删除锁的父路径。定时检查路径被加入到reaper中。当检查时,如果path没有子节点/路径,此路径将被删除。每个应用中CLient应该只创建一个reaper实例。必须将lock path加到这个readper中。reaper会定时的检查删除它们。

ChildReaper

用来清除父节点下所有的空节点。定时的调用getChildren()并将空节点加入到内部管理的reaper中。

注意:应该考虑使用LeaderSelector来运行Reapers,因为它们不需要在每个client运行

5.Apache Curator Client

Curator client使用底层的API, 强烈推荐你是用Curator Framework代替使用CuratorZookeeperClient

1.背景

CuratorZookeeperClient 是ZooKeeper client的包装类。但是提供了更简单方式, 而且可以减少错误的发生。它提供了下列的特性:

  • 持续的连接管理 - ZooKeeper有很多的关于连接管理的警告(你可以到ZooKeeper FAQ查看细节)。CuratorZookeeperClient 可以自动的管理这些事情。
  • retry - 提供一个方式处理retry(重试)。
  • Test ZooKeeper server - 提供一个进程内的ZooKeeper测试服务器用来测试和实验。

2.方法

  • Constructor - 创建一个给定ZooKeeper集群的连接。 你可以传入一个可选的watcher. 必须提供Retry策略
  • getZooKeeper() - 返回管理的ZooKeeper实例. 重要提示: a) 它会花费些许时间等待连接来完成, 在使用其它方法之前你应该校验连接是否完成. b) 管理的ZooKeeper实例可以根据特定的事件而改变。 不要持有实例太长时间. 总是调用getZooKeeper()得到一个新的实例
  • isConnected() - 返回ZooKeeper client当前连接状态
  • blockUntilConnectedOrTimedOut() - block知道连接成功或者超时
  • close() - 关闭连接
  • setRetryPolicy() - 改变retry(重试)策略
  • newRetryLoop() - 分配一个新的Retry Loop(重试循环)

3.Retry Loop(重试循环)

由于各种各样的原因,在zookeeper集群上的操作难免遇到失败的情况。最佳实践表明应该提供重试机制。Retry Loop为此而生。每个操作都被包装在一个Retry Loop中。下面是一个典型的处理流程:

  1. RetryLoop retryLoop = client.newRetryLoop();
  2. while ( retryLoop.shouldContinue() )
  3. {
  4. try
  5. {
  6. // perform your work
  7. ...
  8. // it‘s important to re\-get the ZK instance as there may have been an error and the instance was re\-created
  9. ZooKeeper zk = client.getZookeeper();
  10. retryLoop.markComplete();
  11. }
  12. catch ( Exception e )
  13. {
  14. retryLoop.takeException(e);
  15. }
  16. }

Retry Loop维护一定数量的retry, 它还决定一个错误是否可以要执行retry。 假如一个错误需要retry,Retry策略被调用来决定retry是要要执行,执行多少次才放弃。

很方便地,RetryLoop 提供了一个静态方法使用Callable来执行一个完整retry loop。

  1. RetryLoop.callWithRetry(client, new Callable<Void>()
  2. {
  3. @Override
  4. public Void call() throws Exception
  5. {
  6. // do your work here - it will get retried if needed
  7. return null;
  8. }
  9. });

4.Retry策略(重试策略)

retry策略可以改变retry的行为。它抽象出RetryPolicy接口,包含一个方法public boolean allowRetry(int retryCount, long elapsedTimeMs)。在retry被尝试执行前,allowRetry()被调用,并且将当前的重试次数和操作已用时间作为参数.如果返回true, retry被执行。否则异常被抛出。

Curator本身提供了几个策略(在 com.netflix.curator.retry 包下):

  • ExponentialBackoffRetry:重试一定次数,每次重试sleep更多的时间
  • RetryNTimes:重试N次
  • RetryOneTime:重试一次
  • RetryUntilElapsed:重试一定的时间

-------------------------------------------------------------------------------------------------------------------------------

来自为知笔记(Wiz)

时间: 2024-08-24 02:07:08

03.Curator深入使用的相关文章

Dubbo 微服务系列(03)服务注册

Dubbo 微服务系列(03)服务注册 [TOC] Spring Cloud Alibaba 系列目录 - Dubbo 篇 1. 背景介绍 图1 Dubbo经典架构图 注:本图来源 Dubbo官方架构图 表1 节点角色说明 节点 角色说明 Provider 暴露服务的服务提供方 Consumer 调用远程服务的服务消费方 Registry 服务注册与发现的注册中心 Monitor 统计服务的调用次数和调用时间的监控中心 Container 服务运行容器 在 Dubbo 微服务体系中,注册中心是其

ZooKeeper和Curator相关经验总结

一.关于ZooKeeper的watch用法,需要注意 详细说明如下: ZooKeeper Watches All of the read operations in ZooKeeper - getData(), getChildren(), and exists() - have the option of setting a watch as a side effect. Here is ZooKeeper's definition of a watch: a watch event is o

03 php 数据类型:整数,进制转换,浮点,字符,布尔,数组,空类型,类型转换,算术运算,比较运算

03 数据类型:整数,进制转换,浮点,字符,布尔,数组,空类型,类型转换, 算术运算,比较运算,逻辑运算,短路现象, 三目运算符,字符型运算: 数据类型 整体划分 标量类型: int, float, string, bool 复合类型: array,     object 特殊类型: null,     resouce 整数类型int, integer 3种整数表示法 十进制写法:123: $n1 = 123; 八进制写法: 0123 $n2 = 0123; 十六进制写法: 0x123 $n3

前端开发神器WebStorm--Grunt 搭建环境(03)

通过上一篇前端开发神器WebStorm--自动化工作流(前言),相信大家都Grunt自动化工具有了初步了解. 接下来我就以WROC3000 web为原型,演示一下如何使用Grunt工具提高工作效率,最大程度压缩代码. 1.首先安装node环境 进入官网 下载安装.(记住安装目录) 检测安装成功方法:打开CMD窗口,输入 node --version 会打印出安装的版本号,说明已经安装成功. 2.安装 Grunt 客户端 在CMD 窗口中,切换到node安装盘符,会自动切换到nodejs安装目录.

MyBatis笔记03

1.动态sql 01.if:单独使用if,后面必须有where 1=1 代码:<!-- 需要注意的事项:01. 在xml文件中 特殊字符的使用 &&必须换成 and或者 & < < > > <= <= >= >= ' &apos;" " 02.因为不确定用户输入的到底是哪个参数 所以 where 之后必须加上 1=1 而且 每个条件之前加上 and --> <select id="

Environmental.Science.Limited.ChemHELP.v2.03

Environmental.Science.Limited.ChemHELP.v2.03 VMGSIM.V9.0.46最新版流程模拟软件     chemhelp易于安装和设置(系统要求如下).在一台电脑上,化学制品可以从数据库中选择,输入他 们的全名,或者使用一个搜索,可以指定一个部分的化学名称,中国科学院或联合国的数字,欧共体或欧 共体指数,甚至是一个风险短语.可以为选定的化学物显示的数据包括索引编号.危险符号.芯片分类和 标签.风险短语.物理性质.同义词.以及更多.正如这表明,在数据库中的

zookeeper使用curator进行选主(Leader)

在分布式系统设计中,选主是一个常见的场景.选主是一个这样的过程,通过选主,主节点被选择出来控制其他节点或者是分配任务. 选主算法要满足的几个特征: 1)各个节点均衡的获得成为主节点的权利,一旦主节点被选出,其他的节点可以感知到谁是主节点,被服从分配. 2)主节点是唯一存在的 3)一旦主节点失效,宕机或者断开连接,其他的节点能够感知,并且重新进行选主算法. zookeeper实现了安全可靠的选主机制. 作为zookeeper的高级api封装库curator选主算法主要有以下两个:Leader La

UML大战需求分析——阅读笔记03

读<UML大战需求分析>有感03 状态机图和活动图在样子比较相似,但状态机图是用来为对象的状态及造成状态改变的事件建模.我们大二学习UML统一建模语言状态机图模块时了解到,UML的状态机图主要用于建立对象类或对象的动态行为模型,描述系统中某一个对象所经历的各个状态.引起状态或活动转移的事件,以及因状态或活动转移而伴随的动作.但在以前的学习过程中,我们并没有学到过"伪状态",后经查阅知:伪状态是指在一个状态机中具有状态的形式,同时具有特殊行为的顶点.它是一个瞬时状态,用于构造

条款03:尽可能使用const

01.顶层const和底层const char greeting[] = "Hello"; char* p = ; const char* p = greeting;   //const data,nonconst pointer char* const p = greeting;       //nonconst data,const pointer const char* const p = greeting; //const data,nonconst pointer.*的左右位