JavaとZookeeperを始めよう

JavaとZookeeperの使用開始

1. 概要

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

Nodes within ZooKeeper cluster store their data in a shared hierarchal namespaceは、標準のファイルシステムまたはツリーデータ構造に似ています。

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

2. Setup

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


    org.apache.zookeeper
    zookeeper
    3.4.11

3. ZooKeeperデータモデル– ZNode

ZooKeeperには階層型のネームスペースがあり、ステータス情報、調整情報、位置情報などの調整データを保存する分散ファイルシステムによく似ています。 この情報は異なるノードに保存されます。

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

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

4. インストール

4.1. インストール

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

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

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

注:スタンドアロンモードではレプリケーションがないため、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. ZooKeeper JavaAPIの例

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

6.1. Javaパッケージ

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

  1. org.apache.zookeeper:は、ZooKeeperクライアントライブラリのメインクラスと、ZooKeeperイベントタイプおよび状態の多くの静的定義を定義します。

  2. org.apache.zookeeper.data:アクセス制御リスト(ACL)、ID、統計など、ZNodeに関連付けられた特性を定義します

org.apache.zookeeper.serverorg.apache.zookeeper.server.quorumorg.apache.zookeeper.server.upgradeなどのZooKeeper JavaAPIもサーバー実装で使用されます。

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

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 class, which is the main class of ZooKeeper client libraryのオブジェクトをインスタンス化する必要があります。

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

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

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

6.3. クライアントオペレーション

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

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. 結論

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

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

そしていつものように、このチュートリアルのすべてのソースはover on Githubで見つけることができます。