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提供了一种能够确保数据节点存在的机制,多用于这样的业务场景中:
上层业务希望对一个数据节点进行一些操作,但是操作之前需要确保该节点存在。基于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());
}
}
为了便于开发人员进行ZooKeeper的开发与测试,Curator 提供了一种启动简易ZooKeeper服务的方法——TestingServer。
TestingServer 允许开发人员非常方便地启动一个标准的ZooKeeper服务器,并以此来进行一系列的单元测试。TestingServer在Curator的test包中,需要单独依赖以下Maven依赖来获取:
<dependency>
<groupId>org.apache.curatorgroupId>
<artifactId>curator-testartifactId>
<version>2.4.2version>
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中创建一个临时目录来作为数据存储目录。
上文中提到,开发人员可以利用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 选举。