ZooKeeperクライアント開発
20357 ワード
前述のZooKeeperの原理とサーバクラスタの導入はZooKeeperサーバクラスタの導入を完了し,本稿では公式APIとzkClientの2つの方法でZooKeeperデータの修正と状態監視を実証した.DubboにおけるZooKeeperの役割をコードでシミュレートした.作者:王克鋒出典:https://kefeng.wang/2017/11/10/zookeeper-development/ 著作権:自由転載-非商用-非派生-署名を保持し、転載は作者と出典を明記してください.
1.応用開発
APIドキュメント:https://zookeeper.apache.org/doc/current/api/index.html Javaの例:https://zookeeper.apache.org/doc/current/javaExample.html プログラマガイド:https://zookeeper.apache.org/doc/current/zookeeperProgrammers.html 通常、ZooKeeperアプリケーションは2つのユニットに分けられ、1つは接続を維持し、もう1つはデータを監視します.
1.1主要API create:ノードの作成; delete:ノードを削除する; exists:ノードが存在するか否かを判断する; get data:ノードデータの読み出し; set data:ノードデータを書き込む; get children:ノードのサブノードを取得する; sync:データ同期;
1.2 Zookeeper開発コンポーネント
Document: http://zookeeper.apache.org/doc/r3.4.11/ ZooKeeper 3.4.11 API: https://zookeeper.apache.org/doc/r3.4.11/api/index.html
zookeeperが持参したコンポーネントで、煩雑で信頼性がありません.セッションタイムアウト異常の場合、再接続が煩雑である. watcherは使い捨てであり、使い捨てサブスクリプションを永続サブスクリプションに変更する追加の符号化が必要である. ノードデータはバイナリであり、オブジェクトデータはバイナリ保存に変換する必要がある.
1.2.1 pom.xml
1.2.2 ZookeeperClient.java
1.2.3運転結果
1.3 zkClient開発コンポーネント
公式ZooKeeper APIをカプセル化し、公式APIの欠点を回避した.https://github.com/sgroschupf/zkclient
1.3.1 pom.xml
1.3.2 ZookeeperClient.java
1.3.3運転結果
2.dubboにおけるZooKeeperの応用
ZooKeeperは構成センターとして、サービスアドレスの登録とクエリーを提供する.consumerサブスクリプションサービス(サブスクリプションイベント、サービスアドレスの変化を動的に感知する);provider登録サービス(zkノードの作成);
ZooKeeperにおけるDubboのストレージ構造は以下の通りである(consumerブランチを増やすのは、サービス消費状況の統計を容易にするためである).レベル1:ルートノード(configcenter)、永続ノード; レベル2:各サービス名(serviceName)、永続ノード; レベル3(拡張):ノード分類(nodeType)、provider/consumer、永続ノードを区別するために使用される. レベル4[provider]:特定のserviceNameのプロバイダアドレスリスト(provideAddress)、非永続ノード、providerがラインオフすると自動的にノードが削除され、consumerに自動的に通知されます. レベル4[consumer]:特定のserviceNameのコンシューマアドレスリスト(consumerAddress)は、非永続ノードであり、consumerがラインオフすると自動的に削除されます.
2.1 ServiceProvider.java
ServiceProviderが登録センター(ZooKeeperクラスタ)にサービスを登録するキーコード:
2.2 ServiceConsumer.java
ServiceConsumerは、登録センター(ZooKeeperクラスタ)からサービスプロバイダのアドレスリストのキーコードを取得します.
1.応用開発
APIドキュメント:https://zookeeper.apache.org/doc/current/api/index.html Javaの例:https://zookeeper.apache.org/doc/current/javaExample.html プログラマガイド:https://zookeeper.apache.org/doc/current/zookeeperProgrammers.html 通常、ZooKeeperアプリケーションは2つのユニットに分けられ、1つは接続を維持し、もう1つはデータを監視します.
1.1主要API
1.2 Zookeeper開発コンポーネント
Document: http://zookeeper.apache.org/doc/r3.4.11/ ZooKeeper 3.4.11 API: https://zookeeper.apache.org/doc/r3.4.11/api/index.html
zookeeperが持参したコンポーネントで、煩雑で信頼性がありません.
1.2.1 pom.xml
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
<version>3.4.11version>
dependency>
1.2.2 ZookeeperClient.java
public class ZookeeperClient {
private static Log logger = LogFactory.getLog(ZookeeperClient.class);
public static void main(String args[]) throws IOException, KeeperException, InterruptedException {
//
final String serverUrl = "centos:2181,centos:2182,centos:2183";
ZooKeeper zk = new ZooKeeper(serverUrl, 30000, new Watcher() {
public void process(WatchedEvent event) { // ( , watcher)
String path = event.getPath(); //
Event.EventType type = event.getType(); // ( 、 , )
logger.info("*** : path=" + path + ", type=" + type);
}
});
//
List acl = ZooDefs.Ids.OPEN_ACL_UNSAFE; // ( , )
CreateMode createMode = CreateMode.PERSISTENT; // ( , , )
zk.create("/parentNode", "parentData".getBytes(), acl, createMode);
zk.create("/parentNode/childNode1", "childData1".getBytes(), acl, createMode); //
zk.create("/parentNode/childNode2", "childData2".getBytes(), acl, createMode);
//
logger.info(" : " + zk.getChildren("/parentNode", true)); //
logger.info(" : " + (zk.exists("/parentNode/childNode1", true) != null));
logger.info(" : " + new String(zk.getData("/parentNode/childNode1", true, null))); //
zk.setData("/parentNode/childNode1", "childData1-X".getBytes(), -1); // ( 1M, )
logger.info(" : " + new String(zk.getData("/parentNode/childNode1", true, null))); //
// ( , )
zk.delete("/parentNode/childNode2", -1);
zk.delete("/parentNode/childNode1", -1);
zk.delete("/parentNode", -1);
//
zk.close();
}
}
1.2.3運転結果
15:33:59.215 INFO [ZookeeperClient.java:24] - *** : path=null, type=None
15:33:59.233 INFO [ZookeeperClient.java:36] - : [childNode1, childNode2]
15:33:59.237 INFO [ZookeeperClient.java:37] - : true
15:33:59.240 INFO [ZookeeperClient.java:38] - : childData1
15:33:59.247 INFO [ZookeeperClient.java:24] - *** : path=/parentNode/childNode1, type=NodeDataChanged
15:33:59.247 INFO [ZookeeperClient.java:40] - : childData1-X
15:33:59.252 INFO [ZookeeperClient.java:24] - *** : path=/parentNode, type=NodeChildrenChanged
15:33:59.254 INFO [ZookeeperClient.java:24] - *** : path=/parentNode/childNode1, type=NodeDeleted
1.3 zkClient開発コンポーネント
公式ZooKeeper APIをカプセル化し、公式APIの欠点を回避した.https://github.com/sgroschupf/zkclient
1.3.1 pom.xml
<dependency>
<groupId>com.101tecgroupId>
<artifactId>zkclientartifactId>
<version>0.10version>
dependency>
1.3.2 ZookeeperClient.java
public class ZookeeperClient {
private static Log logger = LogFactory.getLog(ZookeeperClient.class);
public static void main(String args[]) {
//
final String serverUrl = "centos:2181,centos:2182,centos:2183";
ZkClient zk = new ZkClient(serverUrl);
// 、
zk.createPersistent("/parentNode", "parentData"); //
zk.createEphemeral("/parentNode/childNode1", "childData1"); //
zk.createEphemeral("/parentNode/childNode2", "childData2"); //
zk.subscribeChildChanges("/parentNode", new IZkChildListener() { //
public void handleChildChange(String parentPath, List childList) throws Exception {
logger.info("*** : " + parentPath + ", " + childList);
}
});
zk.subscribeDataChanges("/parentNode/childNode1", new IZkDataListener() { // ( )
public void handleDataChange(String path, Object data) throws Exception {
logger.info("*** : " + path + ", " + data);
}
public void handleDataDeleted(String path) throws Exception {
logger.info("*** : " + path);
}
});
//
logger.info(" : " + zk.getChildren("/parentNode"));
logger.info(" : " + zk.exists("/parentNode/childNode1"));
logger.info(" : " + zk.readData("/parentNode/childNode1"));
zk.writeData("/parentNode/childNode1", "childData1-X"); // ( 1M, )
logger.info(" : " + zk.readData("/parentNode/childNode1"));
// ( , )
zk.delete("/parentNode/childNode2");
zk.delete("/parentNode/childNode1");
zk.delete("/parentNode");
//
zk.close();
}
}
1.3.3運転結果
16:17:21.904 INFO [ZookeeperClient.java:42] - : [childNode1, childNode2]
16:17:21.904 INFO [ZookeeperClient.java:43] - : true
16:17:21.909 INFO [ZookeeperClient.java:44] - : childData1
16:17:21.919 INFO [ZookeeperClient.java:46] - : childData1-X
16:17:21.921 INFO [ZookeeperClient.java:33] - *** : /parentNode/childNode1, childData1-X
16:17:21.931 INFO [ZookeeperClient.java:28] - *** : /parentNode, []
16:17:21.951 INFO [ZookeeperClient.java:37] - *** : /parentNode/childNode1
2.dubboにおけるZooKeeperの応用
ZooKeeperは構成センターとして、サービスアドレスの登録とクエリーを提供する.consumerサブスクリプションサービス(サブスクリプションイベント、サービスアドレスの変化を動的に感知する);provider登録サービス(zkノードの作成);
ZooKeeperにおけるDubboのストレージ構造は以下の通りである(consumerブランチを増やすのは、サービス消費状況の統計を容易にするためである).
2.1 ServiceProvider.java
ServiceProviderが登録センター(ZooKeeperクラスタ)にサービスを登録するキーコード:
public class ServiceProvider {
private static Log logger = LogFactory.getLog(ServiceProvider.class);
private static final String rootPath = "/configcenter";
private static final String servicePath = rootPath + "/serviceName";
private static final String zookeeperList = "centos:2181,centos:2182,centos:2183";
public static void main(String args[]) throws UnknownHostException {
ZkClient zk = new ZkClient(zookeeperList);
//
if (!zk.exists(rootPath)) {
zk.createPersistent(rootPath);
}
//
if (!zk.exists(servicePath)) {
zk.createPersistent(servicePath);
}
// IP
String serviceIp = InetAddress.getLocalHost().getHostAddress().toString();
zk.createEphemeral(servicePath + "/" + serviceIp);
//
zk.close();
}
}
2.2 ServiceConsumer.java
ServiceConsumerは、登録センター(ZooKeeperクラスタ)からサービスプロバイダのアドレスリストのキーコードを取得します.
public class ServiceConsumer {
private static Log logger = LogFactory.getLog(ServiceConsumer.class);
private static final String servicePath = "/configcenter/serviceName";
private static final String zookeeperList = "centos:2181,centos:2182,centos:2183";
private static List providerList = null; //
public static void main(String args[]) throws UnknownHostException {
ZkClient zk = new ZkClient(zookeeperList);
//
if (zk.exists(servicePath)) {
providerList = zk.getChildren(servicePath);
} else {
throw new RuntimeException("[" + servicePath + "] not exist.");
}
//
zk.subscribeChildChanges(servicePath, new IZkChildListener() {
public void handleChildChange(String parentPath, List childList) throws Exception {
providerList = childList;
}
});
//
zk.close();
}
}