1. 程式人生 > >Curator原始碼解析(一)原始碼結構和測試程式

Curator原始碼解析(一)原始碼結構和測試程式

Curator是Netflix開源的一套ZooKeeper客戶端框架. Netflix在使用ZooKeeper的過程中發現ZooKeeper自帶的客戶端太底層, 應用方在使用的時候需要自己處理很多事情, 於是在它的基礎上包裝了一下, 提供了一套更好用的客戶端框架. Netflix在用ZooKeeper的過程中遇到的問題, 我們也遇到了, 所以開始研究一下, 首先從他在github上的原始碼, wiki文件以及Netflix的技術blog入手. 

看完官方的文件之後, 發現Curator主要解決了三類問題: 

  • 封裝ZooKeeper client與ZooKeeper server之間的連線處理;
  • 提供了一套Fluent風格的操作API;
  • 提供ZooKeeper各種應用場景(recipe, 比如共享鎖服務, 叢集領導選舉機制)的抽象封裝.

先大概講一下程式碼結構和主要的類,Curator包含了以下資料夾(元件):

Recipes    Implementations of some of the common ZooKeeper"recipes". The implementations are built on top of the CuratorFramework.

構建在Curator Framework框架之上,實現了原生ZooKeeper中的分散式工具特徵recipes。

Framework

  The Curator Framework is a high-level API thatgreatly simplifies using ZooKeeper. It adds many features that build onZooKeeper and handles the complexity of managing connections to the ZooKeepercluster and retrying operations.

提供高層抽象API簡化ZooKeeper的使用,更重要的是封裝了管理到ZooKeeper叢集的連線以及重試機制的複雜性,是Curator對外提供的介面。

Utilities  Various utilities that are useful when usingZooKeeper.

一些使用ZooKeeper過程中有用的工具。

Client A replacement for the bundled ZooKeeper class that takes care ofsome low-level housekeeping and provides some useful utilities.

替換原生ZooKeeper類,封裝操作原生ZooKeeper的底層細節,主要包括前面說的實現了複雜的到ZooKeeper叢集的連線以及重試機制。

Errors How Curator deals with errors, connection issues, recoverableexceptions, etc.

Curator如何處理錯誤,連線問題以及可恢復異常。

Extensions The curator-recipes package implements thecommon recipes that are described in the ZooKeeper documentation. To avoidbloating that package, recipes/applications that have a vertical appeal will beput in separate "extension" packages using the naming convention curator-x-name.

Curator基於ZooKeeper實現的拓展功能,包括直接操作ZooKeeper的服務的動態發現,封裝後以Restful介面提供出來的服務動態發現,以及RPC呼叫等功能,具體以後的文章會講到。

一個典型的Curator的例子就是:

/**
 * An example of the PathChildrenCache. The example "harness" is a command processor
 * that allows adding/updating/removed nodes in a path. A PathChildrenCache keeps a
 * cache of these changes and outputs when updates occurs.
 */
public class PathCacheExample
{
    private static final String     PATH = "/example/cache";
    public static void main(String[] args) throws Exception
    {
        TestingServer       server = new TestingServer();
        CuratorFramework    client = null;
        PathChildrenCache   cache = null;
        try
        {
            client = CuratorFrameworkFactory.newClient(server.getConnectString(), new ExponentialBackoffRetry(1000, 3));
            client.start();

            // in this example we will cache data. Notice that this is optional.
            cache = new PathChildrenCache(client, PATH, true);
            cache.start();

            setValue(client, command, args);
        }
        finally
        {
            CloseableUtils.closeQuietly(cache);
            CloseableUtils.closeQuietly(client);
            CloseableUtils.closeQuietly(server);
        }
}

private static void setValue(CuratorFramework client, String command, String[] args) throws Exception
    {
        if ( args.length != 2 )
        {
            System.err.println("syntax error (expected set <path> <value>): " + command);
            return;
        }

        String      name = args[0];
        if ( name.contains("/") )
        {
            System.err.println("Invalid node name" + name);
            return;
        }
        String      path = ZKPaths.makePath(PATH, name);

        byte[]      bytes = args[1].getBytes();
        try
        {
            client.setData().forPath(path, bytes);
        }
        catch ( KeeperException.NoNodeException e )
        {
            client.create().creatingParentsIfNeeded().forPath(path, bytes);
        }
    }

下一篇文章開始將會通過這個例子詳細分析Curator原始碼。