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 选举。

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