RabbitMQを試してみる

以前↓ActiveMQを使ってチョコっと動かしてみたことあるのですが TomcatでActiveMQを動かしてみる SpringのJmsTemplateを使ってActiveMQにキューイング とか 実際に業務で使わなかったなと。。   今もFTPサーバーとかネットワークファイルシステムとか使って ファイルをアレやコレやしてますが、スリープしてリトライしてxxだったら~とか、 なんだか本質的でない実装をイロイロしなきゃいけない感じでなんだかな~と。   RabbitMQは文献が英語ばかりとか、実装がErlangでされててイザって時に ソース追えないな、、っていうのでビビったりしてましたが、ぼちぼちソレでも 頑張らないとダメかなぁと。   ってことで、今回やりたいのは以下2点。 1. 冗長構成(2ノード立てて、片方落ちても大丈夫的な) 2. MQとかあんまり関係ないけど、アラートメール送信用途で、    クライアント側でMessageの内容比較して全く同じだったら件数だけカウントして捨てる的な   ■ RabbitMQのインストール Ubuntuにインストールするので↓を参考に。 Installing on Debian / Ubuntu(http://www.rabbitmq.com/install-debian.html)   作業はめんどいので全部rootで。。

# vim /etc/apt/sources.list
=> deb http://www.rabbitmq.com/debian/ testing main を追加
# wget http://www.rabbitmq.com/rabbitmq-signing-key-public.asc
# apt-key add rabbitmq-signing-key-public.asc
# apt-get install rabbitmq-server
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
~略~
Starting rabbitmq-server: SUCCESS
rabbitmq-server.
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place

ユーザーの追加やサーバーの起動までやっていただいて楽チンでございます。

# ps -ef | grep rabbitmq | grep -v grep
rabbitmq 15494     1  0 08:52 ?        00:00:00 /usr/lib/erlang/erts-5.8.5/bin/epmd -daemon
rabbitmq 15507     1  0 08:52 ?        00:00:00 /usr/lib/erlang/erts-5.8.5/bin/beam -W w -K true -A30 -P 1048576 -- -root /usr/lib/erlang -progname erl -- -home /var/lib/rabbitmq -- -noshell -noinput -sname rabbit@hoge -boot /var/lib/rabbitmq/mnesia/rabbit@hoge-plugins-expand/rabbit -kernel inet_default_connect_options [{nodelay,true}] -sasl errlog_type error -sasl sasl_error_logger false -rabbit error_logger {file,"/var/log/rabbitmq/rabbit@hoge.log"} -rabbit sasl_error_logger {file,"/var/log/rabbitmq/rabbit@hoge-sasl.log"} -os_mon start_cpu_sup true -os_mon start_disksup false -os_mon start_memsup false -mnesia dir "/var/lib/rabbitmq/mnesia/rabbit@hoge"
rabbitmq 15593 15507  0 08:52 ?        00:00:00 /usr/lib/erlang/lib/os_mon-2.2.7/priv/bin/cpu_sup
rabbitmq 15594 15507  0 08:52 ?        00:00:00 inet_gethost 4
rabbitmq 15595 15594  0 08:52 ?        00:00:00 inet_gethost 4

ulimitの設定とかrabbitmqctlについても書いてあって親切な導入ガイドでございます。 試しに叩いてみると、なんでもJSONな世の中ねー、と。

# rabbitmqctl status
Status of node rabbit@hoge ...
[{pid,15507},
 {running_applications,[{rabbit,"RabbitMQ","2.7.1"},
                        {mnesia,"MNESIA  CXC 138 12","4.5"},
                        {os_mon,"CPO  CXC 138 46","2.2.7"},
                        {sasl,"SASL  CXC 138 11","2.1.10"},
                        {stdlib,"ERTS  CXC 138 10","1.17.5"},
                        {kernel,"ERTS  CXC 138 10","2.14.5"}]},
 {os,{unix,linux}},
 {erlang_version,"Erlang R14B04 (erts-5.8.5) [source] [64-bit] [rq:1] [async-threads:30] [kernel-poll:true]n"},
 {memory,[{total,24210840},
          {processes,9861192},
          {processes_used,9842424},
          {system,14349648},
          {atom,1124433},
          {atom_used,1120204},
          {binary,93928},
          {code,11134393},
          {ets,710720}]},
 {vm_memory_high_watermark,0.399999999619216},
 {vm_memory_limit,840371404}]
...done.

んま、一旦止めて、起動してみます。

# rabbitmqctl stop
Stopping and halting node rabbit@hoge ...
...done.
# rabbitmq-server
Activating RabbitMQ plugins ...
0 plugins activated:


+---+   +---+
|   |   |   |
|   |   |   |
|   |   |   |
|   +---+   +-------+
|                   |
| RabbitMQ  +---+   |
|           |   |   |
|   v2.7.1  +---+   |
|                   |
+-------------------+
AMQP 0-9-1 / 0-9 / 0-8
Copyright (C) 2007-2011 VMware, Inc.
Licensed under the MPL.  See http://www.rabbitmq.com/

VMwareデダ!って感じですね~   ■ クライアントからRabbitMQにアクセスしてみる open technica: RubyからRabbitMQに接続というブログを見つけました。 ひとまず、上記を参考に、RubyのAMQPなクライアントから、その通りにやってみます。   Ruby入ってなかた…w

# ruby -v
The program 'ruby' can be found in the following packages:
 * ruby1.8
 * ruby1.9.1
# apt-get install ruby1.9.1
Reading package lists... Done
Building dependency tree
Setting up ruby1.9.1 (1.9.3.0-1ubuntu2.4) ...
update-alternatives: using /usr/bin/gem1.9.1 to provide /usr/bin/gem (gem) in auto mode.
update-alternatives: using /usr/bin/ruby1.9.1 to provide /usr/bin/ruby (ruby) in auto mode.
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place
# ruby -v
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-linux]

なんかaptでruby1.9.3とか指定出来なくてruby1.9.1でインストールしたけど、 -vすると1.9.3p0ってなっててよくわかりませんが。。。w   んで、gemでAMQP入れようとしたら、、、

# gem install amqp
Fetching: eventmachine-1.0.0.gem (100%)
Building native extensions.  This could take a while...
ERROR:  Error installing amqp:
    ERROR: Failed to build gem native extension.

        /usr/bin/ruby1.9.1 extconf.rb
/usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- mkmf (LoadError)
    from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
    from extconf.rb:2:in `'

mkmfがどうのこうの、、って。 StackOverFlowみてたらRubyのパッケージが-devじゃないとダメよん的な。 http://stackoverflow.com/questions/7645918/require-no-such-file-to-load-mkmf-loaderror ってことで↓で入れて、

# apt-get install ruby1.9.1-dev

一見よさげかと思ったらg++が無いだと…?w

make: g++: Command not found
make: *** [binder.o] Error 127

ってことで入れて、、、

# apt-get install g++

リベンジ、、、何か言ってるけど、ちゃんと入ったみたい。

# gem install amqp
Building native extensions.  This could take a while...
Fetching: amq-protocol-1.0.0.gem (100%)
Fetching: amq-client-0.9.10.gem (100%)
Fetching: amqp-0.9.8.gem (100%)
[Version 0.9.0 to 0.9.4] [BUG] A couple of concurrency issues (race conditions) fixed for apps that actively close and/or reuse channels
[Version 0.9.0 to 0.9.4] [BUG] AMQP::Queue#initialize with :nowait => true no longer fails with NoMethodError
[Version 0.9.0 to 0.9.4] [FEATURE] Automatic recovery mode now works for publishers
Successfully installed eventmachine-1.0.0
Successfully installed amq-protocol-1.0.0
Successfully installed amq-client-0.9.10
Successfully installed amqp-0.9.8
4 gems installed

上記に記載されている以下のスクリプトをまんまで、実行してみます。 Sample AMQP consumer/producer for RabbitMQ with direct exchange(https://gist.github.com/1868565)   ↓立ち上げておいて、、

# ruby consumer.rb

↓で突っ込んで、、

# ruby producer.rb
sent: Hello, world

consumer.rbの方の窓に↓が表示される~

Hello, world

↓なんかOKっぽいっすね~

# rabbitmqctl list_queues name messages_ready
Listing queues ...
amq.gen-QYHVVH_he0umwnL8k4bEUL  0
...done.

んで、ノードを再起動してみます。

# rabbitmqctl stop
Stopping and halting node rabbit@hoge ...
...done.
# rabbitmq-server
Activating RabbitMQ plugins ...
0 plugins activated:


+---+   +---+
|   |   |   |
|   |   |   |
|   |   |   |
|   +---+   +-------+
|                   |
| RabbitMQ  +---+   |
|           |   |   |
|   v2.7.1  +---+   |
|                   |
+-------------------+
~略~
broker running
^Z
[1]+  Stopped                 rabbitmq-server
# bg
[1]+ rabbitmq-server &

んでもってもっかいlist_queuesみると↓なくなってます。

# rabbitmqctl list_queues name messages_ready
Listing queues ...
...done.

consumer.rbの窓みると、『Erlang has closed』って表示されてました。   ■ RabbitMQの管理画面用プラグインをインストール クラスタ構成作ろうかなーって思ってググってたら ↓CAさんのドンピシャなブログを発見しました。 はじめての RabbitMQ|サイバーエージェント 公式エンジニアブログ   rabbitmq_managementというのを入れるとWeb画面でホゲホゲ出来るようになる、と。 さっそく叩いてみると、、あ、ですよね?的な、、。

# rabbitmq-plugins list
rabbitmq-plugins: command not found

と思ったらパスが通ってないだけで、フルパス指定すると、、

# /usr/lib/rabbitmq/lib/rabbitmq_server-2.7.1/sbin/rabbitmq-plugins list
[ ] amqp_client                       0.0.0
[ ] eldap                             0.0.0-git
[ ] erlando                           0.0.0
[ ] mochiweb                          1.3-rmq0.0.0-git
[ ] rabbitmq_auth_backend_ldap        0.0.0
[ ] rabbitmq_auth_mechanism_ssl       0.0.0
[ ] rabbitmq_consistent_hash_exchange 0.0.0
[ ] rabbitmq_federation               0.0.0
[ ] rabbitmq_jsonrpc                  0.0.0
[ ] rabbitmq_jsonrpc_channel          0.0.0
[ ] rabbitmq_jsonrpc_channel_examples 0.0.0
[ ] rabbitmq_management               0.0.0
[ ] rabbitmq_management_agent         0.0.0
[ ] rabbitmq_management_visualiser    0.0.0
[ ] rabbitmq_mochiweb                 0.0.0
[ ] rabbitmq_shovel                   0.0.0
[ ] rabbitmq_shovel_management        0.0.0
[ ] rabbitmq_stomp                    0.0.0
[ ] rabbitmq_tracing                  0.0.0
[ ] rfc4627_jsonrpc                   0.0.0-git
[ ] webmachine                        1.7.0-rmq0.0.0-hg

って事で↓のように突っ込みます。RabbitMQの再起動が必要ということで。

# /usr/lib/rabbitmq/lib/rabbitmq_server-2.7.1/sbin/rabbitmq-plugins enable rabbitmq_management
The following plugins have been enabled:
  mochiweb
  webmachine
  rabbitmq_mochiweb
  amqp_client
  rabbitmq_management_agent
  rabbitmq_management

Plugin configuration has changed. Restart RabbitMQ for changes to take effect.

わかりやすいようにチョコっとだけ中身書き換えて、 producer.rb

9     exchange = channel.direct 'amq.direct'

consumer.rb

 9     queue = channel.queue('Hello')
10     exchange = channel.direct 'amq.direct'

consumer.rbを落としてproducer.rbをドカドカ叩くと↓になって、 consumer.rb叩くと未読が0になります~。便利。   クラスタ構成の構築~ 複数台用意すればアレなのですが、今回もポート番号変えるだけでやりくりしやす。 ググってたら、これまたドンピシャなブログを発見しました↓ RabbitMQ のクラスタリング機能にキューのミラーリングが追加されたので RabbitFoot (AnyEvent::RabbitMQ) から試してみる そうそう、まさに知りたかったのが↑で、且つ、ミラーリング出来るんだ~ヽ(´∀`)ノ   が、ポート変えて実行しても、なんかうまくいかず。

broker running (の後に、、)
Erlang has closed

って出ちゃう。ログみると rabbitmq_management がなんかアレみたいで。。

=ERROR REPORT==== 3-Dec-2012::11:19:29 ===
** Generic server rabbit_mochiweb_registry terminating
** Last message in was {add,rabbit_mgmt,#Fun,
                            #Fun,
                            {[],"RabbitMQ Management"}}
** When Server state == undefined
** Reason for termination ==
** {{case_clause,
        {error,
            {eaddrinuse,
                {child,undefined,
                    {rabbit_mochiweb_web,mgmt},
                    {rabbit_mochiweb_web,start,[{mgmt,[{port,55672}]}]},
                    transient,5000,worker,dynamic}}}},
    [{rabbit_mochiweb_sup,ensure_listener,1},
     {rabbit_mochiweb_registry,handle_call,3},
     {gen_server,handle_msg,5},
     {proc_lib,init_p_do_apply,3}]}

一旦 rabbitmq_management をdisabledにしてから再起動。

#  /usr/lib/rabbitmq/lib/rabbitmq_server-2.7.1/sbin/rabbitmq-plugins disable rabbitmq_management
The following plugins have been disabled:
  mochiweb
  webmachine
  rabbitmq_mochiweb
  amqp_client
  rabbitmq_management_agent
  rabbitmq_management

Plugin configuration has changed. Restart RabbitMQ for changes to take effect.
  • rabbit1
# RABBITMQ_NODE_PORT=5672 RABBITMQ_NODENAME=rabbit1 rabbitmq-server
Activating RabbitMQ plugins ...
0 plugins activated:
  • rabbit2
# RABBITMQ_NODE_PORT=5673 RABBITMQ_NODENAME=rabbit2 rabbitmq-server
Activating RabbitMQ plugins ...
0 plugins activated:

そんなこんなで、いよいよ、クラスタのセットアップをします。

# rabbitmqctl -n rabbit2 stop_app
# rabbitmqctl -n rabbit2 reset
# rabbitmqctl -n rabbit2 cluster rabbit1@`hostname -s`
# rabbitmqctl -n rabbit2 start_app

そうすると↓の設定ファイルに書き込まれて、次起動した時も有効になるんですかね~? /var/lib/rabbitmq/mnesia/rabbit2/cluster_nodes.config   んで、クラスタのステータスを見てみると↓っぽく見えやす。

# rabbitmqctl -n rabbit1 cluster_status
Cluster status of node rabbit1@hoge ...
[{nodes,[{disc,[rabbit1@hoge]},{ram,[rabbit2@hoge]}]},
 {running_nodes,[rabbit2@hoge,rabbit1@hoge]}]
...done.

consumerとproducerでx-ha-policyをallにして~とかやりたかったけどタイムアップ。。また次回~

RabbitMQ in Action: Distributed Messaging for Everyone
Alvaro Videla Jason J. W. Williams
Manning Pubns Co
売り上げランキング: 29555