本稿は
CloudFoundry Advent Calendar の 6日目の記事として投稿させて頂いています.
RabbitMQ は 2.6.x から複数台による Active-Active Standby 構成をとることができる.以前は DRBD による Active-Stanby 構成しかとれなかったので,2.6 以降で,より柔軟性が上がっている.
前準備
まず,高可用構成をとるには,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 でホストネームを渡してあげる部分.
#!/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 のについて追いかけて説明したい.