本文翻译自 Netflix[1]技术博客文章《Introducing Curator - The Netflix ZooKeeper Library》,原文由 Netflix 工程师,Curator 作者 Jordan Zimmerman 编写,原文在这里。接触 Curator 已经快一年时间,期间有过写一篇介绍性文章的念头,但一直没有动手,后来回顾手头的资料,觉得其实这篇文章虽然简洁了一点,但也是一个很好的介绍,于是翻译在这里。仅用于学习,请勿用于其它用途。
Netflix 的开源
Netflix 致力于开源,我们过去写过相关的博客,今天我们公布 Netflix 开源项目的门户网页。网页托管在 Github 上,有几个项目在并行推进当中(其中包括我们今天对外发布的 Curator):
- Curator - Netflix 的 ZooKeeper 库
- Astyanax - Netflix 的 Cassandra 客户端
- Priam - Cassandra 的跨进程备份/恢复功能,Token 管理,配置中心化管理
- CassJMeter - 运行 Cassandra 测试的 JMeter 插件
ZooKeeper
ZooKeeper 是一个高性能的分布式协调服务框架。它将通用的服务,如命名,配置管理,同步,分组服务等,通过简单的接口展现出来。要全面的了解 ZooKeeper,请参考以下网页:
难以用好
ZooKeeper 本身自带一个 Java 客户端,但使用这个客户端繁琐[2]而且容易出错。客户端的使用者需要做大量的手动维护性工作。比如:
连接问题
- 初始化连接:ZooKeeper 客户端与服务器进行握手,这需要花一些时间。如果握手未完成,任何要与服务器端同步执行的方法(如,create(),getData()等)都会抛出异常。
- Failover:如果 ZooKeeper 客户端与服务器连接断开,它会 failover 到集群中另外一台服务器。然后,这个过程会使客户端退回到”初始化连接”的模式。
- Session 过期:有些边际情况可以导致 ZooKeeper session 过期。客户端需要监视这个状态,关闭并重建 ZooKeeper 客户端实例。
恢复问题
- 当在 Server 创建顺序节点(sequential ZNode)时,有可能出现这种情况:节点成功创建了,但 server 在将节点名返回给客户端之前崩溃了。
- ZooKeeper 客户端可能会抛出几个可恢复的异常,使用者需要捕捉这些异常并做重试操作。
Recipe[3]方面
- 标准的 ZooKeeper recipe(如锁,选 leader 等)只是得到最低程序的描述,要正确地编写出来比较困难。
- 有一些重要的边界情况在 recipe 描述里没有提到。例如,锁 recipe 的描述中,没有说到如何处理服务器成功创建了顺序(Sequential)/临时(Ephemeral)节点,但在向客户端返回结点名之前就崩溃的情况。如果没有得到正确处理,可能会导致死锁。
- 某些使用场景下,必须要注意可能出现的连接问题。例如,选 leader 过程要监视连接的稳定性。如果连接到的服务器崩溃了,leader 就不能假定自己继续为 leader,除非已经成功 failover 到另外的服务器。
上述问题(和其它类似的问题)必须由每个 ZooKeeper 使用者来处理。问题解决方案既不容易编写,也不是显而易见的,需要消耗相当多的时间。而 Curator 处理了所有的问题。
Curator 是什么
Curator n ˈkyoor͝ˌātər:,展品或者其它收藏品的看守者,管理员,ZooKeeper 的 Keeper。它由 3 个相关的项目组成:
- curator-client - ZooKeeper 自带客户端的替代者,它负责处理低层次的维护工作,并提供某些有用的小功能
- curator-framework - Curator Framework 大大地简化 ZooKeeper 使用的高层次 API。它在 ZooKeeper 客户端之上添加了很多功能,并处理了与 ZooKeeper 集群连接管理和重试操作的复杂性。
- curator-recipes - ZooKeeper 某些通用 recipe 的实现。它是基于 Curator Framework 之上实现的。
Curator 专注于锁,选 Leader 等这些 recipe。大部分对 ZooKeeper 感兴趣的人不需要关心连接管理等细节。他们想要的只是简单的使用这些 recipe。Curator 就是以此作为目标。
Curator 通过以下方式处理了使用 ZooKeeper 的复杂度:
- 重试机制:Curator 支持可插拔式的(pluggable)重试机制。所有会产生可恢复异常的 ZooKeeper 操作都会在配置好的重试策略下得到重试。Curator 自带了几个标准的重试策略(如二元指数后退策略)。
- 连接状态监视:Curator 不断监视 ZooKeeper 连接的状态,Curator 用户可以监听连接状态变化并相应的作出回应。
- ZooKeeper 客户端实例管理:Curator 通过标准的 ZooKeeper 类实例来管理与 ZooKeeper 集群的实际连接。然而,这些实例是管理在内部(尽管你若需要也可以访问),在需要的时候被重新创建。因此,Curator 提供了对 ZooKeeper 集群的可靠处理(不像 ZooKeeper 自带的实现)。
- 正确,可靠的 recipe:Curator 实现了大部分重要的 ZooKeeper recipe(还有一些附加的 recipe)。它们的实现使用了 ZooKeeper 的最佳实践,处理了所有已知的边界情况(像前面所说的)。
- Curator 专注于那些让你的代码更强健,因为你完全专心于你感兴趣的 ZooKeeper 功能,而不用担心怎么正确完成那些的维护性工作。
ZooKeeper 在 Netflix
ZooKeeper/Curator 在 Netflix 得到了广泛的使用。使用情景有:
- InterProcessMutex 在各种顺序 ID 生成器中被用来保证值的唯一性
- Cassandra 备份
- TrackID 服务
- 我们的 Chukwa 收集器使用 LeaderSelector 来做各种维护性的任务
- 我们用了一些第三方的服务,但它们只允许有限数目的并发用户。InterProcessSemphore 被用来处理这个。
- 各种 Cache
获取 Curator
- Curator 二进制被上传到了 Maven Central,这让获取它变得很容易
- Curator 的源代码放在 Github 上托管[4]:https://github.com/Netflix/curator
- 全面的文档放在:https://github.com/Netflix/curator/wiki
注:
[1] Netflix 是一个美国的在线 DVD 租赁公司,后来转型到网络流媒体服务。参考维基百科 Netflix 词条。
[2] 原文为 non-trivial,意思应该是搞反了。
[3] Recipe 中文意思为“菜谱,配方”,感觉翻译过来不能很好的表达英文”一系列约定步骤”的意思,故不译。
[4] Curator 在去年(2013 年)年中已经正式成为 Apache Incubator 项目,代码改为托管在 Github Apache 的对应目录下。主页和文档的位置也有所变化。