1. 概要

Apache ZooKeeper は、分散アプリケーションの開発を容易にする分散調整サービスです。 これは、Apache Hadoop、HBase、 others などのプロジェクトで、リーダーの選出、構成管理、ノード調整、サーバーリース管理などのさまざまなユースケースで使用されます。

ZooKeeperクラスター内のノードは、標準のファイルシステムまたはツリーデータ構造に類似した共有階層名前空間にデータを格納します。

この記事では、ApacheZookeeperのJavaAPIを使用して、ZooKeeper内に保存されている情報を保存、更新、および削除する方法について説明します。

2. セットアップ

Apache ZooKeeper Javaライブラリの最新バージョンは、ここにあります。

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.11</version>
</dependency>

3. ZooKeeperデータモデル– ZNode

ZooKeeperには、ステータス情報、調整情報、場所情報などの調整データを格納する分散ファイルシステムによく似た、階層的な名前空間があります。 この情報はさまざまなノードに保存されます。

ZooKeeperツリー内のすべてのノードはZNodeと呼ばれます。

各ZNodeは、データまたはACLの変更のバージョン番号とタイムスタンプを維持します。 また、これにより、ZooKeeperはキャッシュを検証し、更新を調整できます。

4. インストール

4.1. インストール

最新のZooKeeperリリースは、こちらからダウンロードできます。 その前に、ここで説明されているシステム要件を満たしていることを確認する必要があります。

4.2. スタンドアロンモード

この記事では、最小限の構成で済むため、ZooKeeperをスタンドアロンモードで実行します。 ドキュメントこちらに記載されている手順に従ってください。

注:スタンドアロンモードではレプリケーションがないため、ZooKeeperプロセスが失敗すると、サービスがダウンします。

5. ZooKeeperCLIの例

次に、ZooKeeperコマンドラインインターフェイス(CLI)を使用してZooKeeperと対話します。

bin/zkCli.sh -server 127.0.0.1:2181

上記のコマンドは、スタンドアロンインスタンスをローカルで起動します。 次に、ZNodeを作成し、ZooKeeper内に情報を保存する方法を見てみましょう。

[zk: localhost:2181(CONNECTED) 0] create /MyFirstZNode ZNodeVal
Created /FirstZnode

ZooKeeper階層名前空間のルートにZNode‘MyFirstZNode’を作成し、それに‘ZNodeVal’を書き込みました。

フラグを渡していないため、作成されたZNodeは永続的です。

次に、‘get’ コマンドを発行して、ZNodeに関連付けられたデータとメタデータをフェッチします。

[zk: localhost:2181(CONNECTED) 1] get /FirstZnode

“Myfirstzookeeper-app”
cZxid = 0x7f
ctime = Sun Feb 18 16:15:47 IST 2018
mZxid = 0x7f
mtime = Sun Feb 18 16:15:47 IST 2018
pZxid = 0x7f
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 22
numChildren = 0

set 操作を使用して、既存のZNodeのデータを更新できます。

例えば:

set /MyFirstZNode ZNodeValUpdated

これにより、MyFirstZNodeのデータがZNodeValからZNodeValUpdatedに更新されます。

6.6。 ZooKeeperJavaAPIの例

次に、Zookeeper Java APIを見て、ノードを作成し、ノードを更新して、いくつかのデータを取得しましょう。

6.1. Javaパッケージ

ZooKeeper Javaバインディングは、主に2つのJavaパッケージで構成されています。

  1. org.apache.zookeeper これは、ZooKeeperクライアントライブラリのメインクラスと、ZooKeeperイベントタイプおよび状態の多くの静的定義を定義します。
  2. org.apache.zookeeper.data :アクセス制御リスト(ACL)、ID、統計など、ZNodeに関連付けられた特性を定義します

また、ZooKeeper Java APIは、 org.apache.zookeeper.server org.apache.zookeeper.server.quorum orgなどのサーバー実装で使用されます。 apache.zookeeper.server.upgrade

ただし、これらはこの記事の範囲を超えています。

6.2. ZooKeeperインスタンスへの接続

次に、すでに実行中のZooKeeperとの接続および切断に使用されるZKConnectionクラスを作成しましょう。

public class ZKConnection {
    private ZooKeeper zoo;
    CountDownLatch connectionLatch = new CountDownLatch(1);

    // ...

    public ZooKeeper connect(String host) 
      throws IOException, 
      InterruptedException {
        zoo = new ZooKeeper(host, 2000, new Watcher() {
            public void process(WatchedEvent we) {
                if (we.getState() == KeeperState.SyncConnected) {
                    connectionLatch.countDown();
                }
            }
        });

        connectionLatch.await();
        return zoo;
    }

    public void close() throws InterruptedException {
        zoo.close();
    }
}

ZooKeeperサービスを使用するには、アプリケーションは最初に、ZooKeeperクライアントライブラリのメインクラスであるZooKeeperクラスのオブジェクトをインスタンス化する必要があります。

connect メソッドでは、ZooKeeperクラスのインスタンスをインスタンス化しています。 また、接続を受け入れるためにZooKeeperからの WatchedEvent を処理し、それに応じてCountDownLatchのcountdownメソッドを使用してconnectメソッドを終了するコールバックメソッドを登録しました

サーバーへの接続が確立されると、セッションIDがクライアントに割り当てられます。 セッションを有効に保つために、クライアントは定期的にハートビートをサーバーに送信する必要があります。

クライアントアプリケーションは、セッションIDが有効である限り、ZooKeeperAPIを呼び出すことができます。

6.3. クライアントの操作

次に、 ZKManager インターフェイスを作成します。このインターフェイスは、ZNodeの作成やデータの保存、ZNodeデータのフェッチと更新など、さまざまな操作を公開します。

public interface ZKManager {
    public void create(String path, byte[] data)
      throws KeeperException, InterruptedException;
    public Object getZNodeData(String path, boolean watchFlag);
    public void update(String path, byte[] data) 
      throws KeeperException, InterruptedException;
}

上記のインターフェースの実装を見てみましょう。

public class ZKManagerImpl implements ZKManager {
    private static ZooKeeper zkeeper;
    private static ZKConnection zkConnection;

    public ZKManagerImpl() {
        initialize();
    }

    private void initialize() {
        zkConnection = new ZKConnection();
        zkeeper = zkConnection.connect("localhost");
    }

    public void closeConnection() {
        zkConnection.close();
    }

    public void create(String path, byte[] data) 
      throws KeeperException, 
      InterruptedException {
 
        zkeeper.create(
          path, 
          data, 
          ZooDefs.Ids.OPEN_ACL_UNSAFE, 
          CreateMode.PERSISTENT);
    }

    public Object getZNodeData(String path, boolean watchFlag) 
      throws KeeperException, 
      InterruptedException {
 
        byte[] b = null;
        b = zkeeper.getData(path, null, null);
        return new String(b, "UTF-8");
    }

    public void update(String path, byte[] data) throws KeeperException, 
      InterruptedException {
        int version = zkeeper.exists(path, true).getVersion();
        zkeeper.setData(path, data, version);
    }
}

上記のコードでは、connectおよびdisconnect呼び出しは、以前に作成されたZKConnectionクラスに委任されます。 create メソッドを使用して、バイト配列データから指定されたパスにZNodeを作成します。 デモンストレーションのみを目的として、ACLを完全に開いたままにしました。

作成されると、ZNodeは永続的であり、クライアントが切断しても削除されません。

getZNodeDataメソッドでZooKeeperからZNodeデータをフェッチするロジックは非常に簡単です。 最後に、 update メソッドを使用して、指定されたパス上のZNodeの存在を確認し、存在する場合はそれをフェッチします。

さらに、データを更新するために、最初にZNodeの存在を確認し、現在のバージョンを取得します。 次に、ZNodeのパス、データ、現在のバージョンをパラメーターとしてsetDataメソッドを呼び出します。 ZooKeeperは、渡されたバージョンが最新バージョンと一致する場合にのみデータを更新します。

7. 結論

分散アプリケーションを開発する場合、ApacheZooKeeperは分散調整サービスとして重要な役割を果たします。 特に、共有構成の保存、マスターノードの選択などのユースケース向けです。

ZooKeeperは、ZooKeeper ZNodeとのシームレスな通信のために、クライアント側のアプリケーションコードで使用されるエレガントなJavaベースのAPIも提供します。

そしていつものように、このチュートリアルのすべてのソースは、Githubにあります。