フロムスクラッチ開発者ブログ

from scratch Engineers' Blog

Apache ZooKeeperの内部解析してみる vol.2 ~ZooKeeper操作編~

こんにちは、fukuです。

前回に引き続きApache ZooKeeperについて書いていきます。前回ではZooKeeperの概要の説明を行いました。ZooKeeperではznodeから構成されるデータノードを管理しており、クラアントはAPIを通じてデータノードの操作を行うことができます。 今回は実際にZooKeeperを操作することでZooKeeperのAPIなどについての理解を深めていきましょう。

インストール

ZooKeeperのダウンロードページApache ZooKeeper - Releasesからダウンロードを行います。今回はZooKeeperのバージョン3.5.3-beta(何事も先取って検証)を対象とし、macOS Sierra(バージョン10.12.6)のOS環境上で検証を行いました。 ダウンロードしたzookeeper-3.5.3-beta.tar.gzファイルを任意のディレクトリに置き、以下のコマンド群を実行することで、ZooKeeperの起動の準備をします。

$ tar zxvf zookeeper-3.5.3-beta.tar.gz
$ cd zookeeper-3.5.3-beta.tar.gz
$ cp conf/zoo_sample.cfg conf/zoo.cfg

上記のコマンドを実行でZooKeeperが起動できるようになったので、以下のコマンドからスタンドアローンモードでZooKeeperをバックグラウンド(デフォルトポート2181)で起動することができます。

$ bin/zkServer.sh start

またサブコマンドを変更することでフォアグラウンドで実行することも可能です。

$ bin/zkServer.sh start-foreground

サーバを停止する時は、以下のコマンドを実行してください。

$ bin/zkServer.sh stop

ZooKeeperの利用

サーバを立ち上げた状態で、ZooKeeperのディレクトリにおいて以下のコマンドを実行することで、クライアントを起動することができます。

$ ./bin/zkCli.sh

無事に接続が確立すると、クライアントコマンドの待ち受け状態になります。ここでhelpを入力して、コマンド一覧を表示してみましょう(実際にはhelpというコマンドは存在せず、存在しないコマンドを入力することで以下のようなUSAGE情報が表示されます)。

[zk: localhost:2181(CONNECTED) 0] help
ZooKeeper -server host:port cmd args
    addauth scheme auth
    close 
    config [-c] [-w] [-s]
    connect host:port
    create [-s] [-e] [-c] [-t ttl] path [data] [acl]
    delete [-v version] path
    deleteall path
    delquota [-n|-b] path
    get [-s] [-w] path
    getAcl [-s] path
    history 
    listquota path
    ls [-s] [-w] [-R] path
    ls2 path [watch]
    printwatches on|off
    quit 
    reconfig [-s] [-v version] [[-file path] | [-members serverID=host:port1:port2;port3[,...]*]] | [-add serverId=host:port1:port2;port3[,...]]* [-remove serverId[,...]*]
    redo cmdno
    removewatches path [-c|-d|-a] [-l]
    rmr path
    set [-s] [-v version] path data
    setAcl [-s] [-v version] path acl
    setquota -n|-b val path
    stat [-w] path
    sync path
Command not found: Command not found help

今回はいくつかのコマンドを実際に実行することで、ZeeKeeperで行えることをみていきましょう。

データツリーの操作

まずlsコマンドを使ってZooKeeperのデータノードを覗いてみましょう。

[zk: localhost:2181(CONNECTED) 1] ls /
[zookeeper]

上記から、データノードのルートノードには[zookeeper]のznodeがあることがわかります。[zookeeper]ノードはZooKeeperのシステム情報を管理するためのノードとなります。

それでは次にcreateコマンドからznodeを作成してみましょう。

[zk: localhost:2181(CONNECTED) 2] create /clients ""
Created /clients
[zk: localhost:2181(CONNECTED) 3] ls /              
[zookeeper, clients]

このようにcreateコマンドの第1引数にznodeの名前、第2引数でznodeに格納するデータを指定することで、znodeが作成されます。 ちなみに今回のcreateコマンドでできたznodeはPERSISTENTノードとなります。

getコマンドではznodeの情報を参照することができます。

[zk: localhost:2181(CONNECTED) 4] get /clients

ここでは、出力としてcreate`コマンドで指定したデータ(今回は空文字列)が出力されます。

続いてsetコマンドで、znodeのデータを変更してみましょう。

[zk: localhost:2181(CONNECTED) 5] set /clients "hogehoge"
[zk: localhost:2181(CONNECTED) 6] get /clients           
hogehoge

上位のようにznodeに格納されているデータが空文字列から"hogehoge"に変わっていることがわかります。znodeのデータセットで注意しなければならないことは、データが置き換わるということです。そのためデータを追記したりすることはできません。

クライアントのセッションを終了するにはquitコマンドを実行します。

[zk: localhost:2181(CONNECTED) 7] quit
Quitting...
2017-12-30 20:32:17,295 [myid:] - INFO  [main:ZooKeeper@687] - Session: 0x160a6c05dcf0004 closed
2017-12-30 20:32:17,298 [myid:] - INFO  [main-EventThread:ClientCnxn$EventThread@520] - EventThread shut down for session: 0x160a6c05dcf0004

znodeのモード

ここでは前回記事で紹介したznodeのいろいろなモードを試していきたいと思います。createコマンドにはモードを指定するオプションが存在しており、オプションを指定する事によって、いろいろなモードのznodeを作成することができます。

PERSISTENT

PERSISTENTモードのznodeは、先ほどのようにcreateのオプションなしで作成することができます。

[zk: localhost:2181(CONNECTED) 0] create /clients/c1 "PERSISTENT"
Created /clients/c1

PERSISTENTモードではznodeが永続化されるので、セッションを終了してから、再度セッションを開始してもznodeがそのまま存在することが確認できます。

PERSISTENTモードのznodeを削除するにはdeleteコマンドによって、明示的に削除を行う必要があります。

[zk: localhost:2181(CONNECTED) 1] delete /clients/c1
[zk: localhost:2181(CONNECTED) 2] ls /clients
[]

EPHEMERAL

EPHEMERALモードではznodeの作成を行なったセッションが切断されると、znodeは自動的に削除されます。createコマンドで-eオプションの指定でEPHEMERALモードのznodeを作成することができます。ここではクライアントを2つ立ち上げてEPHEMERALモードのznodeをみていきます。

#  クライアント1
[zk: localhost:2181(CONNECTED) 0] create -e /clients/ephemeral-client "EPHEMERAL"
Created /clients/ephemeral-client

#  クライアント2
[zk: localhost:2181(CONNECTED) 0] ls /clients
[ephemeral-client]

#  クライアント1
[zk: localhost:2181(CONNECTED) 1] quit
Quitting...
2017-12-30 20:47:29,178 [myid:] - INFO  [main:ZooKeeper@687] - Session: 0x160a6c05dcf0006 closed
2017-12-30 20:47:29,180 [myid:] - INFO  [main-EventThread:ClientCnxn$EventThread@520] - EventThread shut down for session: 0x160a6c05dcf0006

# クライアント2
[zk: localhost:2181(CONNECTED) 1] ls /clients
[]

上記のようにクライアント1でEPHEMERALモードのznodeを作成すると、クライアント2でも作成したznodeの確認が行えます。次にクライアントのセッションを終了して、クライアント2でznodeの確認を行うとEPHEMERALモードのznodeのノードが削除されていることがわかります。

CONTAINER

CONTAINERモードのznodeは自身の子ノードが削除されると自動的にznodeが削除されます。createコマンドの-cオプションによって、CONTAINERモードを指定することができます。

[zk: localhost:2181(CONNECTED) 0] create -c /container ""
Created /container
[zk: localhost:2181(CONNECTED) 1] create  /container/child ""
Created /container/child
[zk: localhost:2181(CONNECTED) 2] delete /container/child 
[zk: localhost:2181(CONNECTED) 3] ls /
[clients, container, zookeeper]

<しばらくした後>

[zk: localhost:2181(CONNECTED) 4] ls /
[clients, zookeeper]

上記のようにCONTAINERモードのznode(/container)を作成して、子ノードを作成・削除します。その後にCONTAINERモードのznodeはすぐには削除されませんが、一定時間ののちにZooKeeperによって自動的に削除されます。

PERSISTENT_TTL

PERSISTENT_TTLモードがznodeの生存時間を指定することができ、指定時間後にZooKeeperによって自動的に削除されます。createコマンドの-tオプションによってPERSISTENT_TTLモードを指定することができます。

[zk: localhost:2181(CONNECTED) 0] create -t 600 /ttl_node ""
[zk: localhost:2181(CONNECTED) 1] ls /
[clients, ttl_node, zookeeper]

<しばらくした後(600ms以上)>

[zk: localhost:2181(CONNECTED) 2] ls /
[clients, zookeeper]

生存時間は-tオプションの後ろにミリ秒単位で指定します(上記は600ms)。作成直後はznodeが存在していることが確認できますが、600ms後しばらくしてから、確認するとznodeが削除されていることが確認できます。

ここで注意しなければいけないのは、ちょうど600ms後に削除されるのではなく、ZooKeeperの定期的にTTLモード(CONTAINERモードも同様)の削除を行うタイミングで削除が行われるという点です。そのため600ms後に初めてのZooKeeperの削除サイクルのタイミングが来た時に削除されます。デフォルトではZooKeeperの削除サイクルの時間間隔は2000msとなります。

長くなってしまったので、今回はこの辺で....

おわりに

今回は実際にZooKeeperをスタンドアローンモードで起動して、CLIからデータツリーに対するさまざまな操作を行いました。 次回はソースコードからデータツリーがどのように管理されているのかをみていこうと思います。

ではでは...