前回のエントリの最後に「Programmers Guideをみると、クライアントプログラムなどの作成方法などが解説されていますが、とりあえず今回は HBase のほうに進むということで、ZooKeeper についての話はいったんここで終わります。」なんて書きましたが、HBase のクラスタ環境を構築するためにはどうも ZooKeeper もクラスタ環境になっている必要があるようなので、ZooKeeper をクラスタ化してみます。
設定については、前回(d:id:k155e1:20100420:1271757128)を参照してください。
マニュアルでいうと Running Replicated ZooKeeper あたりからでしょうか。
HBase のところで出てきますが、HBase をクラスタで動作させる場合、ZooKeeper Quorum を事前に起動させておく必要があります(HDFS もですが)。
で、Quorum って何?という感じだったのですが、ZooKeeper のマニュアルにこういう一文がありました。
A replicated group of servers in the same application is called a quorum.
ちなみに、辞典をひくと「定」とか「数」とかいうらしい(ほんとか?)。余計にわけがわからなくなってきた。
まぁ、それはいいとして、とりあえず同一アプリケーション内のサーバグループ、ということでしょうか。
- ZooKeeper クラスタ用設定
同一 quorum に所属するサーバは同一の設定を持つ、という定義になるようです。
というより、同一の設定をもつ ZooKeeper のサーバが1つのグループであり、それを quorum と呼ぶ、というほうが正しい?
サンプルとなる記述は以下。
tickTime=2000 dataDir=/var/zookeeper clientPort=2181 initLimit=5 syncLimit=2 server.1=zoo1:2888:3888 server.2=zoo2:2888:3888 server.3=zoo3:2888:3888
ドキュメントではここで initLimit と syncLimit の説明をしています。
単位は tickTime になるようで、上記設定の場合、tickTime の単位はミリ秒のため、1 tickTime は 2秒、ということは、initLimit は 5 × 2秒の 10秒、syncLimit は 2 × 2秒の 4秒という感じだそうです。
server.X
は ZooKeeper が起動しているサーバを記述する感じで。
サーバ名(と思われる)のうしろの 2888 と 3888 はポート番号で、前のポート(2888)は他のサーバと接続するために使われるらしい。後者のほうは(quorumにおける?)リーダーを決めるための通信に使われるっぽいが、よくわかりません。
というわけで、今回の実験環境だとこんな感じでしょうか。
tickTime=2000 dataDir=/var/zookeeper clientPort=2181 initLimit=5 syncLimit=2 server.1=myhdfs1:2888:3888 server.2=myhdfs2:2888:3888 server.3=myhdfs3:2888:3888
- myidファイルの準備
前述のように zoo.cfg ファイルを修正して myhdfs1 にて ZooKeeper サーバを起動しようとしたところ、エラーが発生して怒られたのですが、どうも、conf/zoo.cfg の dataDir で指定した場所(/home/issei/tmp/zookeeper/)に、myid
というファイルを用意する必要があるようです。
このmyid
ファイルには、server.X
の X にあたる数値を記述しておく必要があるみたいです。
myhdfs1> cat /home/issei/tmp/zookeeper/myid 1
今回、myhdfs2 は 2、myhdfs3 は 3 が記述された myid ファイルを用意しました。
myhdfs2> pwd /home/issei/tmp/zookeeper myhdfs2> cat myid 2
myhdfs2> pwd /home/issei/tmp/zookeeper myhdfs3> cat myid 3
- 動作確認1(事前確認)
前回は myhdfs1 のみで ZooKeeper を起動したので、myhdfs1 の設定を、myhdfs2、myhdfs3 に反映して起動してみます。
一応、起動前の各サーバの jps の結果。
myhdfs1> jps 17497 NameNode 17753 SecondaryNameNode 17946 TaskTracker 17825 JobTracker 20445 Jps 17613 DataNode
myhdfs2> jps 32536 Jps 30593 DataNode 30698 TaskTracker
myhdfs3> jps 13488 Jps 11815 DataNode 11914 TaskTracker
- 動作確認2(失敗編)
myhdfs1 で ZooKeeper サーバを起動するのですが、zkServer.sh start 時、myid ファイルが存在しないとエラーになります。
myhdfs1> ./bin/zkServer.sh start JMX enabled by default Using config: /home/issei/app/zookeeper-3.3.0/bin/../conf/zoo.cfg Starting zookeeper ... STARTED [issei@myhdfs1 zookeeper]$ 2010-04-21 13:54:45,476 - INFO [main:QuorumPeerConfig@90] - Reading configuration from: /home/issei/app/zookeeper-3.3.0/bin/../conf/zoo.cfg 2010-04-21 13:54:45,487 - INFO [main:QuorumPeerConfig@287] - Defaulting to majority quorums 2010-04-21 13:54:45,491 - FATAL [main:QuorumPeerMain@83] - Invalid config, exiting abnormally org.apache.zookeeper.server.quorum.QuorumPeerConfig$ConfigException: Error processing /home/issei/app/zookeeper-3.3.0/bin/../conf/zoo.cfg at org.apache.zookeeper.server.quorum.QuorumPeerConfig.parse(QuorumPeerConfig.java:110) at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:99) at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:76) Caused by: java.lang.IllegalArgumentException: /home/issei/tmp/zookeeper/myid file is missing at org.apache.zookeeper.server.quorum.QuorumPeerConfig.parseProperties(QuorumPeerConfig.java:297) at org.apache.zookeeper.server.quorum.QuorumPeerConfig.parse(QuorumPeerConfig.java:106) ... 2 more Invalid config, exiting abnormally
ログをみると、/home/issei/tmp/zookeeper/myid file is missing
と言われていることがわかります。
この場合、myid ファイルを用意してください。
- 動作確認3(びっくりした編)
myid を用意して、myhdfs1 で ZooKeeper サーバを起動したところ、以下のようなログが定期的に・・・
2010-04-21 14:03:56,831 - INFO [Thread-1:QuorumCnxManager$Listener@436] - My election bind port: 3888 2010-04-21 14:03:56,856 - INFO [QuorumPeer:/0:0:0:0:0:0:0:0:2181:QuorumPeer@610] - LOOKING 2010-04-21 14:03:56,860 - INFO [QuorumPeer:/0:0:0:0:0:0:0:0:2181:FastLeaderElection@649] - New election. My id = 1, Proposed zxid = 13 2010-04-21 14:03:56,871 - WARN [WorkerSender Thread:QuorumCnxManager@361] - Cannot open channel to 2 at election address myhdfs2/172.29.11.112:3888 java.net.ConnectException: Connection refused at sun.nio.ch.Net.connect(Native Method) at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:507) at java.nio.channels.SocketChannel.open(SocketChannel.java:146) at org.apache.zookeeper.server.quorum.QuorumCnxManager.connectOne(QuorumCnxManager.java:347) at org.apache.zookeeper.server.quorum.QuorumCnxManager.toSend(QuorumCnxManager.java:320) at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.process(FastLeaderElection.java:353) at org.apache.zookeeper.server.quorum.FastLeaderElection$Messenger$WorkerSender.run(FastLeaderElection.java:326) at java.lang.Thread.run(Thread.java:619) ... 続く ...
よくよくみると、myhdfs2 へ接続しようとしている感じです。
※この時点で、myhdfs1 上でしか ZooKeeper を起動していない。
- 動作確認4(気を取り直して編)
というわけで、myhdfs1/myhdfs2/myhdfs3 を連続で起動してみることにする。
myhdfs1 ⇒ myhdfs2 ⇒ myhdf3 の順番で、bin/zkServer.sh start
を実行したところ、タイミングの違いで myhdfs1/myhdfs2 では前述の警告(WARN)が表示されましたが、最後に起動した myhdfs3 では警告は出ませんでした。
起動後の各サーバの jps の結果を以下に。
myhdfs1> jps 17497 NameNode 17753 SecondaryNameNode 17946 TaskTracker 20834 Jps 17825 JobTracker 17613 DataNode 20792 QuorumPeerMain
QuorumPeerMain というのが起動していることがわかります。
myhdfs2> jps 30593 DataNode 32754 Jps 32716 QuorumPeerMain 30698 TaskTracker
こちらも。
myhdfs3> jps 13679 Jps 11815 DataNode 11914 TaskTracker 13635 QuorumPeerMain
こちらも。
というわけで、見た目上は、ZooKeeper クラスタが起動したように思える。
- 動作確認5(クライアントから接続してみる編)
で、クライアントから接続してみる。
まずは myhdfs1 から、サーバをローカルとして接続を試みる。
以下、接続してls /
してquit
するという単純な接続確認。
myhdfs1> cd ~/app/zookeeper myhdfs1> ./bin/zkCli.sh -server myhdfs1 Connecting to myhdfs1 2010-04-21 14:16:34,111 - INFO [main:Environment@97] - Client environment:zookeeper.version=3.3.0-925362, built on 03/19/2010 18:38 GMT 2010-04-21 14:16:34,117 - INFO [main:Environment@97] - Client environment:host.name=xxx.yyy.zzz 2010-04-21 14:16:34,118 - INFO [main:Environment@97] - Client environment:java.version=1.6.0_18 ... ログ ... 2010-04-21 14:16:34,238 - INFO [main-SendThread(myhdfs1:2181):ClientCnxn$SendThread@908] - Socket connection established to myhdfs1/172.29.11.201:2181, initiating session 2010-04-21 14:16:34,262 - INFO [main-SendThread(myhdfs1:2181):ClientCnxn$SendThread@701] - Session establishment complete on server myhdfs1/172.29.11.111:2181, sessionid = 0x1281ec516d70001, negotiated timeout = 30000 WATCHER:: WatchedEvent state:SyncConnected type:None path:null [zk: myhdfs1(CONNECTED) 0] ls / [zookeeper] [zk: myhdfs1(CONNECTED) 1] quit Quitting... 2010-04-21 14:16:53,440 - INFO [main:ZooKeeper@538] - Session: 0x1281ec516d70001 closed myhdfs1>
大丈夫のようです。
次に、myhdfs1 から myhdfs3 をサーバに指定してつないで見ます。
myhdfs1> ./bin/zkCli.sh -server myhdfs3 Connecting to myhdfs3 2010-04-21 14:19:58,475 - INFO [main:Environment@97] - Client environment:zookeeper.version=3.3.0-925362, built on 03/19/2010 18:38 GMT ... ログ... [zk: myhdfs3(CONNECTING) 0] 2010-04-21 14:19:58,684 - INFO [main-SendThread(myhdfs3:2181):ClientCnxn$SendThread@701] - Session establishment complete on server myhdfs3/172.29.11.113:2181, sessionid = 0x3281ec4fd4b0000, negotiated timeout = 30000 WATCHER:: WatchedEvent state:SyncConnected type:None path:null [zk: myhdfs3(CONNECTED) 0] ls / [zookeeper] [zk: myhdfs3(CONNECTED) 1] quit Quitting... 2010-04-21 14:20:03,936 - INFO [main:ZooKeeper@538] - Session: 0x3281ec4fd4b0000 closed myhdfs1>
大丈夫のようです。
念のため、myhdfs2 から myhdfs3 に接続し、create /zk_test my_data
をしてみます。
myhdfs2> ./bin/zkCli.sh -server myhdfs3 Connecting to myhdfs3 2010-04-21 14:21:36,015 - INFO [main:Environment@97] - Client environment:zookeeper.version=3.3.0-925362, built on 03/19/2010 18:38 GMT ... ログ ... Welcome to ZooKeeper! 2010-04-21 14:21:36,189 - INFO [main-SendThread(myhdfs3:2181):ClientCnxn$SendThread@701] - Session establishment complete on server myhdfs3/172.29.11.112:2181, sessionid = 0x3281ec4fd4b0001, negotiated timeout = 30000 WATCHER:: WatchedEvent state:SyncConnected type:None path:null JLine support is enabled [zk: myhdfs3(CONNECTED) 0] ls / [zookeeper] [zk: myhdfs3(CONNECTED) 1] create /zk_test my_data Created /zk_test [zk: myhdfs3(CONNECTED) 2] ls / [zookeeper, zk_test] [zk: myhdfs3(CONNECTED) 3] get /zk_test my_data cZxid = 0x100000008 ctime = Wed Apr 21 14:22:07 JST 2010 mZxid = 0x100000008 mtime = Wed Apr 21 14:22:07 JST 2010 pZxid = 0x100000008 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 7 numChildren = 0 [zk: myhdfs3(CONNECTED) 4] delete /zk_test [zk: myhdfs3(CONNECTED) 5] ls / [zookeeper] [zk: myhdfs3(CONNECTED) 6] quit Quitting... 2010-04-21 14:22:10,458 - INFO [main:ZooKeeper@538] - Session: 0x3281ec4fd4b0001 closed myhdfs2>
というわけで、一通り大丈夫のようです。
- 動作確認6(こうするとどうなる?編)
クラスタということで、myhdfs1 に接続して /zk_test を作成し、別のクライアントから myhdfs3 に接続して /zk_test を参照してみます。
myhdfs2 から myhdfs1 に接続し、/zk_test を作成
[zk: myhdfs1(CONNECTED) 1] ls / [zookeeper] [zk: myhdfs1(CONNECTED) 2] create /zk_test my_data Created /zk_test [zk: myhdfs1(CONNECTED) 3] ls / [zookeeper, zk_test] [zk: myhdfs1(CONNECTED) 4] get /zk_test my_data cZxid = 0x10000000c ctime = Wed Apr 21 14:32:38 JST 2010 mZxid = 0x10000000c mtime = Wed Apr 21 14:32:38 JST 2010 pZxid = 0x10000000c cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 7 numChildren = 0
この状態で、myhdfs1 から myhdfs3 に接続し、/zk_test を get してみると
[zk: myhdfs3(CONNECTED) 0] get /zk_test my_data cZxid = 0x10000000c ctime = Wed Apr 21 14:32:38 JST 2010 mZxid = 0x10000000c mtime = Wed Apr 21 14:32:38 JST 2010 pZxid = 0x10000000c cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 7 numChildren = 0
とれますねー。ctime/mtime あたりが同じなので、同じなのでしょう。
というわけで、/zk_test を delete して動作確認は完了ということで。
- 動作確認7(ステータス確認編)
マニュアルで、zoo.cfg のサーバ記述のところで、leaderを決めるとか書いてありましたが、zkServer.sh status
で確認できるようです。
コンソールにログがでるとやっぱりうっとうしいので、log4j.properties の rootLogger から CONSOLE を削除して再起動してみたときの例。
myhdfs2/myhdfs3 で zkServer.sh status を実行すると
myhdfs2> ./bin/zkServer.sh status JMX enabled by default Using config: /home/issei/app/zookeeper-3.3.0/bin/../conf/zoo.cfg Mode: follower
という感じで、Mode: follower
となります。
このとき、myhdfs1 でステータスを確認すると
myhdfs1> ./bin/zkServer.sh status JMX enabled by default Using config: /home/issei/app/zookeeper-3.3.0/bin/../conf/zoo.cfg Mode: leader
となりました(邪魔なコンソールログは削除)。
それで、myhdfs3/myhdfs2/myhdfs1 の順番で log4j.properties を書き換えて再起動したところ、myhdfs1 が leader ではなくなっていました。
myhdfs1> ./bin/zkServer.sh status JMX enabled by default Using config: /home/issei/app/zookeeper-3.3.0/bin/../conf/zoo.cfg Mode: follower
調べてみたところ、myhdfs3 が leader になっていました。
というわけで、leader が落ちると、ちゃんと引き継いでくれるということがわかりました。とさ。
以上、長くなりましたが、これでまた HBase に戻れます。