EC2 で動かしている Ubuntu Server 11.10 に RabbitMQ クラスタを構築したのでその時の手順をブログに残しておきます。ホスト名の設定で若干手こずりました…。

RabbitMQをインストール

オフィシャルで配布されているパッケージを使うのがお手軽です。

cd /tmp
wget wget http://www.rabbitmq.com/releases/rabbitmq-server/v2.8.1/rabbitmq-server_2.8.1-1_all.deb
sudo apt-get install erlang-nox
sudo dpkg -i rabbitmq-server_2.8.1-1_all.deb

下記コマンドでエラーが出なければ、正常にRabbitMQが起動しています。

sudo rabbitmqctl status

RabbitMQの初期設定

RabbitMQはデフォルトでノード名がインストールしたサーバのhostname -sになっています。このノード名を変更するには /etc/rabbitmq/rabbitmq-env.conf でNODENAMEを指定すれば良いのですが、何故かNODENAMEにはFQDNが使えません。

このままだと、別のRabbitMQサーバをクラスタに追加する時にノード名の不一致が起き、正常に追加出来ないという罠が待っています。まぁ、/etc/hosts に全サーバのホスト名を書いていけば問題無いのですが、EC2だとインスタンスの再起動でIPとホスト名が変わったりするので、あまり現実的ではありませんね。極力ドメイン名で処理したいところです。

そこで /etc/rabbitmq/rabbitmq-env.conf でFQDNが使えるようにRabbitMQ本体に若干手を加えます。といってもオプションを書き換えるだけです。

書き換える前にサーバを停止しておきます。

sudo /etc/init.d/rabbitmq-server stop

/usr/lib/rabbitmq/lib/rabbitmq_server-2.8.1/sbin/rabbitmq-server

--- rabbitmq-Server2012-04-18 16:17:39.168100001 +0900
+++ rabbitmq-Server2012-04-18 16:17:13.304100001 +0900
@@ -102,7 +102,7 @@
 exec erl \
     ${RABBITMQ_EBIN_PATH} \
     ${RABBITMQ_START_RABBIT} \
-    -sname ${RABBITMQ_NODENAME} \
+    -name ${RABBITMQ_NODENAME} \
     -boot ${RABBITMQ_BOOT_FILE} \
     ${RABBITMQ_CONFIG_ARG} \
     +W w \

/usr/lib/rabbitmq/lib/rabbitmq_server-2.8.1/sbin/rabbitmqctl

--- rabbitmqctl2012-04-18 16:12:54.016100001 +0900
+++ rabbitmqctl2012-04-18 16:12:32.828100000 +0900
@@ -31,7 +31,7 @@
     -noinput \
     -hidden \
     ${RABBITMQ_CTL_ERL_ARGS} \
-    -sname rabbitmqctl$$ \
+    -name rabbitmqctl$$ \
     -s rabbit_control \
     -nodename $RABBITMQ_NODENAME \
     -extra "$@"

/etc/rabbitmq/rabbitmq-env.conf は下記のようにします。

NODENAME=rabbit@rabbit1.foo.bar.internal

これでRabbitMQを再度起動させてエラーが出なければ設定完了です。

クラスタ化する

rabbit1.foo.bar.internal と rabbit2.foobar.internal に対して、上記手順に則ってRabbitMQをインストールしたと仮定します。

rabbit1を初期化する

rabbit1% sudo rabbitmqctl stop_app
rabbit1% sudo rabbitmqctl reset

rabbit1上でrabbit2をクラスタに参加させる

rabbit1% sudo rabbitmqctl cluster rabbit2.foo.bar.internal
rabbit1% sudo rabbitmqctl start_app

クラスタに追加されているか確認する

rabbit1% sudo rabbitmqctl cluster_status
 
Cluster status of node 'rabbit@rabbit1.foo.bar.internal' ...
[{nodes,[{disc,['rabbit@rabbit2.foo.bar.internal']},
         {ram,['rabbit@rabbit1.foo.bar.internal']}]},
 {running_nodes,['rabbit@rabbit2.foo.bar.internal',
                 'rabbit@rabbit1.foo.bar.internal']}]
...done.

追加されてますね。rabbit2からも確認してみます。

rabbit2% sudo rabbitmqctl cluster_status
 
Cluster status of node 'rabbit@rabbit2.foo.bar.internal' ...
[{nodes,[{disc,['rabbit@rabbit2.foo.bar.internal']},
         {ram,['rabbit@rabbit1.foo.bar.internal']}]},
 {running_nodes,['rabbit@rabbit1.foo.bar.internal',
                 'rabbit@rabbit2.foo.bar.internal']}]
...done.

これでrabbit1, rabbit2どちらに接続してもキューをpublish, subscribeすることが出来ます。クラスタ化自体はそこまで難しくないと思います。

詳しくはオフィシャルドキュメントに全部書いてあるので、そちらを参照してください。