Zookeeper--Curator常用工具類

ZKPaths

ZKPaths提供了一些簡單的API來構建ZNode路徑、遞歸創建和刪除節點等,其使用方式如下:

//工具類ZKPaths使用示例
public class ZKPaths_Sample {
    static String path = "/curator_zkpath_sample";
    static CuratorFramework client = CuratorFrameworkFactory
            .builder()
            .connectString("127.0.0.1:2181")
            .sessionTimeoutMs(5000)
            .retryPolicy(new ExponentialBackoffRetry(1000, 3))
            .build();

    public static void main(String[] args) throws Exception {
        client.start();
        ZooKeeper zooKeeper = client.getZookeeperClient().getZooKeeper();
        System.out.println(ZKPaths.fixForNamespace(path, "sub"));
        System.out.println(ZKPaths.makePath(path, "sub"));

        System.out.println(ZKPaths.getNodeFromPath("/curator-zkpath_sample/sub1"));

        ZKPaths.PathAndNode pn = ZKPaths.getPathAndNode("/curator_zkpath_sample/sub1");
        System.out.println(pn.getPath());
        System.out.println(pn.getNode());

        String dir1 = path + "/child1";
        String dir2 = path + "/child2";
        ZKPaths.mkdirs(zooKeeper, dir1);
        ZKPaths.mkdirs(zooKeeper, dir2);
        System.out.println(ZKPaths.getSortedChildren(zooKeeper, path));

        ZKPaths.deleteChildren(client.getZookeeperClient().getZooKeeper(), path, true);

    }
}
/curator_zkpath_sample/sub
/curator_zkpath_sample/sub
sub1
/curator_zkpath_sample
sub1
[child1, child2]

EnsurePath

EnsurePath提供了一種能夠確保數據節點存在的機制,多用於這樣的業務場景中:

上層業務希望對一個數據節點進行一些操作,但是操作之前需要確保該節點存在。基於ZooKeeper提供的原始API接口,爲解決上述場景的問題,開發人員需要首先對該節點進行一個判斷,如果該節點不存在,那麼就需要創建節點。而與此同時,在分佈式環境中,在A機器試圖進行節點創建的過程中,由於併發操作的存在,另一臺機器,如B機器,也在同時創建這個節點,於是A機器創建的時候,可能會拋出諸如“節點已經存在”的異常。因此開發人員還必須對這些異常進行單獨的處理,邏輯通常非常瑣碎。

EnsurePath正好可以用來解決這些煩人的問題,它採取了靜默的節點創建方式,其內部實現就是試圖創建指定節點,如果節點已經存在,那麼就不進行任何操作,也不對外拋出異常,否則正常創建數據節點。

//工具類EnsurePath使用示例
public class EnsurePathDemo {
    static String path = "/zk-book/c1";
    static CuratorFramework client = CuratorFrameworkFactory.builder()
            .connectString("127.0.0.1:2181")
            .sessionTimeoutMs(5000)
            .retryPolicy(new ExponentialBackoffRetry(1000, 3))
            .build();

    public static void main(String[] args) throws Exception {
        client.start();
        client.usingNamespace("zk-book");

        EnsurePath ensurePath = new EnsurePath(path);
        ensurePath.ensure(client.getZookeeperClient());
        ensurePath.ensure(client.getZookeeperClient());

        EnsurePath ensurePath2 = client.newNamespaceAwareEnsurePath("/c1");
        ensurePath2.ensure(client.getZookeeperClient());
    }
}

TestingServer

爲了便於開發人員進行ZooKeeper的開發與測試,Curator 提供了一種啓動簡易ZooKeeper服務的方法——TestingServer。

TestingServer 允許開發人員非常方便地啓動一個標準的ZooKeeper服務器,並以此來進行一系列的單元測試。TestingServer在Curator的test包中,需要單獨依賴以下Maven依賴來獲取:

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-test</artifactId>
            <version>2.4.2</version>
        </dependency>
public class TestingServer_Sample {
    static String path = "/zookeeper";

    public static void main(String[] args) throws Exception {
        TestingServer server = new TestingServer(2182, new File("/home/acton_zhang/software/Zookeeper"));

        CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString("127.0.0.1:2182")
                .sessionTimeoutMs(5000)
                .retryPolicy(new ExponentialBackoffRetry(1000, 3))
                .build();
        client.start();
        System.out.println(client.getChildren().forPath(path));
        server.close();
    }
}
[quota]

TestingServer允許開發人員自定義ZooKeeper服務器對外服務的端口和dataDir路徑。如果沒有指定dataDir,那麼Curator 默認會在系統的臨時目錄java. io.tmpdir中創建一個臨時目錄來作爲數據存儲目錄。

TestingCluster

上文中提到,開發人員可以利用TestingServer來非常方便地在單元測試中啓動一個ZooKeeper服務器,同樣,Curator 也提供了啓動ZooKeeper集羣的工具類。

TestingCluster是一個可以模擬ZooKeeper集羣環境的Curator工具類,能夠便於開發人員在本地模擬由n臺機器組成的集羣環境。下面我們將通過模擬一個由3臺機器組成的ZooKeeper集羣的場景來了解TestingCluster工具類的使用。

public class TestingCluster_Sample {
    public static void main(String[] args) throws Exception {
        TestingCluster cluster = new TestingCluster(3);
        cluster.start();
        Thread.sleep(2000);

        TestingZooKeeperServer leader = null;
        for (TestingZooKeeperServer zs : cluster.getServers()) {
            System.out.print(zs.getInstanceSpec().getServerId() + "-");
            System.out.print(zs.getQuorumPeer().getServerState() + "-");
            System.out.print(zs.getInstanceSpec().getDataDirectory().getAbsolutePath());
            if (zs.getQuorumPeer().getServerState().equals("leading")) {
                leader = zs;
            }
        }
        leader.kill();
        System.out.println("--After leader kill:");
        for (TestingZooKeeperServer zs: cluster.getServers()) {
            System.out.print(zs.getInstanceSpec().getServerId() + "-");
            System.out.print(zs.getQuorumPeer().getServerState() + "-");
            System.out.print(zs.getInstanceSpec().getDataDirectory().getAbsolutePath());
        }
        cluster.stop();
    }
}

在上面這個示例程序中,我們模擬了一個由3臺機器組成的ZooKeeper集羣,同時在運行期間,將Leader服務器Kill掉。從程序運行的輸出結果中可以看到,在Leader服務器被Kill後,其他兩臺機器重新進行了Leader 選舉。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章