本当はどの辺りをいじったら CloudFoundry から RabbitMQ を cluster setup できるのか調査…したかったのだが,そこまで終わらなかったので,VMware つながり && 昨日の y_wakai さんによる RabbitMQ の記事つながりで, RabbitMQ のクラスタセットアップについてまとめておく.
RabbitMQ は 2.6.x から複数台による Active-Active Standby 構成をとることができる.以前は DRBD による Active-Stanby 構成しかとれなかったので,2.6 以降で,より柔軟性が上がっている.
前準備
最新の RabbitMQ をインストールするには,http://www.rabbitmq.com/install-debian.html が参考になる.インストールが終了し,RabbitMQ がマシン h1, h2, h3 で動作していると仮定する.
まず,高可用構成をとるには,RabbitMQ のインスタンス識別子である cookie を同一にしておく必要がある.Debian の場合,cookie ファイルは /var/lib/rabbitmq/.erlang.cookie にある.もし編集していない場合は,
h1 $ echo "cookie" > /var/lib/rabbitmq/.erlang.cookie h2 $ echo "cookie" > /var/lib/rabbitmq/.erlang.cookie h3 $ echo "cookie" > /var/lib/rabbitmq/.erlang.cookie
などとして,クラスタに参加させたいノードの cookie を併せておく.
前知識
高可用構成のセットアップに入る前に,いくつかクラスタセットアップに必要なクラスタのノードの種類について説明する.クラスタのノードの種類には RAM ノードと Disk ノードの2種類がある.その名前の通り,RAM ノードのキューの状態はメモリの中にのみ保存され永続化は行われない.一方,Disk ノードのキューの状態は外部記憶に永続化される.ただし,複数台 Disk モードで動作させたとしても,複製はディスクに書くことを保証しないので注意.DRBD の Bモードで動作させている状態だと思えば良い.高可用構成のクラスタ内には,最低でも1台の Disk ノードが必要なので注意.
高可用構成のセットアップ
高可用構成のセットアップを行うには. rabbitmqctl コマンドを用いる.
h2 $ rabbitmqctl stop_app # Erlang は起動させたまま RabbitMQ プロセスを停止 h2 $ rabbitmqctl reset # RabbitMQ の保持している状態,および DB を初期化 h2 $ rabbitmqctl cluster rabbit@h1 # rabbitmq@h1 をディスクノード,rabbitmq@h2 をRAMノードにしてセットアップ h2 $ rabbitmqctl start_app # RabbitMQ プロセスを再開
これで,h1 をDiskノード, h2 を RAMノードにしてセットアップが完了した.
ポイントとしては, rabbitmqctl cluster で選択したノードが Disk ノードになることだ.
クラスタの状態を調べるには rabbitmq cluster_status を使う.
h1 $ rabbitmqctl cluster_status # クラスタ設定を調べる [{nodes,[{disc,[rabbit@h1]},{ram,[rabbit@h2]}]}, {running_nodes,[rabbit@h1,rabbit@h2]}] h2 $ rabbitmqctl cluster_status [{nodes,[{disc,[rabbit@h1]},{ram,[rabbit@h2]}]}, {running_nodes,[rabbit@h1, rabbit@h2 ]}]
disc,となっているのが Disk ノード,ram となっているのが RAM ノードである.
3台構成でも同様に行ける.
h3 $ rabbitmqctl stop_app # Erlang は起動させたまま RabbitMQ プロセスを停止 h3 $ rabbitmqctl reset # RabbitMQ の保持している状態,および DB を初期化 h3 $ rabbitmqctl cluster rabbit@h1 # rabbitmq@h1 をディスクノード,rabbitmq@h2 をRAMノードにしてセットアップ h3 $ abbitmqctl start_app # RabbitMQ プロセスを再開 h1 $ rabbitmqctl cluster_status h2 $ rabbitmqctl cluster_status h3 $ rabbitmqctl cluster_status
h1 と h2 など,複数ノードを disc ノードにしたい場合は,
$ rabbitmqctl cluster rabbit@h1 rabbit@h2
とすれば良い.
ついでに,昨日の記事にもあった Bunny のライブラリについての補足もしておく.
Bunny のドキュメント中には,リモートの RabbitMQ の接続を行う方法が記述されていない.その方法を知るには,コードを読んで追いかける必要がある.以前調査を行ったので,以下に,リモートの RabbitMQ に接続して enqueue, deque するサンプルを示す.ポイントは,Bunny.new する箇所で :host でホストネームを渡してあげる部分.
Bunny のドキュメント中には,リモートの RabbitMQ の接続を行う方法が記述されていない.その方法を知るには,コードを読んで追いかける必要がある.以前調査を行ったので,以下に,リモートの RabbitMQ に接続して enqueue, deque するサンプルを示す.ポイントは,Bunny.new する箇所で :host でホストネームを渡してあげる部分.
#!/usr/bin/env ruby require "bunny" if ARGV.size < 3 puts "Arguments Error! " exit(1) end hostname = ARGV.shift.to_s num = ARGV.shift.to_i msgsize = ARGV.shift.to_i b = Bunny.new(:host => hostname, :persistent=>false, :immediate=>true) val = "a" * msgsize # start a communication session with the amqp server b.start b.tx_select # declare a queue q = b.queue("test1") # declare default direct exchange which is bound to all queues e = b.exchange("") def push(b, e, num, val) num.times do |num| # publish a message to the exchange which then gets routed to the queue e.publish(val, :key => 'test1') b.tx_commit end end def pop(q) while msg = q.pop(:ack => true)[:payload] if msg == :queue_empty break else q.ack end end end push(b, e, num, val) pop(q)
というわけで,次回こそは RabbitMQ と vcap のについて追いかけて説明したい.
No comments:
Post a Comment