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 選舉。