Skip to content

Framework

Randgalt edited this page Dec 21, 2012 · 5 revisions

Introducing Curator Framework

The Curator Framework is a high-level API that greatly simplifies using ZooKeeper. It adds many features that build on ZooKeeper and handles the complexity of managing connections to the ZooKeeper cluster and retrying operations. Some of the features are:

  • Automatic connection management:
  • There are potential error cases that require ZooKeeper clients to recreate a connection and/or retry operations. Curator automatically and transparently (mostly) handles these cases.
  • Cleaner API:
  • simplifies the raw ZooKeeper methods, events, etc.
  • provides a modern, fluent interface
  • Recipe implementations (see Recipes):
  • Leader election
  • Shared lock
  • Path cache and watcher
  • Distributed Queue
  • Distributed Priority Queue
  • ...

Allocating a Curator Framework Instance

CuratorFrameworks are allocated using the CuratorFrameworkFactory which provides both factory methods and a builder for creating instances. IMPORTANT: CuratorFramework instances are fully thread-safe. You should share one CuratorFramework per ZooKeeper cluster in your application.

The factory methods (newClient()) provide a simplified way of creating an instance. The Builder gives control over all parameters. Once you have a CuratorFramework instance, you must call the start() method. At the end of your application, you should call close().

CuratorFramework API

The CuratorFramework uses a Fluent-style interface. Operations are constructed using builders returned by the CuratorFramework instance. When strung together, the methods form sentence-like statements. e.g.

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");

Methods

create() Begins a create operation. Call additional methods (mode or background) and finalize the operation by calling forPath()
delete() Begins a delete operation. Call additional methods (version or background) and finalize the operation by calling forPath()
checkExists() Begins an operation to check that a ZNode exists. Call additional methods (watch or background) and finalize the operation by calling forPath()
getData() Begins an operation to get a ZNode's data. Call additional methods (watch, background or get stat) and finalize the operation by calling forPath()
setData() Begins an operation to set a ZNode's data. Call additional methods (version or background) and finalize the operation by calling forPath()
getChildren() Begins an operation to get a ZNode's list of children ZNodes. Call additional methods (watch, background or get stat) and finalize the operation by calling forPath()
inTransaction() Begins an atomic ZooKeeper transaction. Combine create, setData, check, and/or delete operations and then commit() as a unit.

Notifications

Notifications for background operations and watches are published via the ClientListener interface. You register listeners with the CuratorFramework instance using the addListener() method. The listener implements two methods:

eventReceived() A background operation has completed or a watch has triggered. Examine the given event for details
clientClosedDueToError() An unrecoverable error has occurred. The CuratorFramework instance has been shut down

ClientEvent

The ClientEvent object is a super-set POJO that can hold every type of background notification and triggered watch. The useful fields of ClientEvent depend on the type of event which is exposed via the getType() method.

Event Type Event Methods
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()
WATCHED getWatchedEvent()

Namespaces

Because a ZooKeeper cluster is a shared environment, it's vital that a namespace convention is observed so that various applications that use a given cluster don't use conflicting ZK paths.

The CuratorFramework has a concept of a "namespace". You set the namespace when creating a CuratorFramework instance (via the Builder). The CuratorFramework will then prepend the namespace to all paths when one of its APIs is called. i.e.

CuratorFramework    client = CuratorFrameworkFactory.builder().namespace("MyApp") ... build();
…
client.create().forPath("/test", data);
// node was actually written to: "/MyApp/test"

Temporary Connections

For temporary connections over unreliable networks, a limited feature Temporary Framework is available.

Clone this wiki locally