RabbitMQ でお手軽 Client-Server モデルを実現する
Erlang のコードは一行も出てきません。
以前作った RabbitFoot を使うので、Perl のコードしか出てきませんが、RabbitMQ(AMQP) を理解する助けになると思います。
事前準備
Client から Server へ Request を送るための Queue を用意します。
% /path/to/rabbit_foot declare_queue -q test_q Declared queue queue: test_q message_count: 0 consumer_count: 0
durable オプションを付けていないので、RabbitMQ の終了と共に、この Queue は削除されます。
この状態で Bind の一覧を確認すると…
% /path/to/scripts/rabbitmqctl list_bindings
Listing bindings ...
test_q test_q []
Exchange が空文字列、Routing Key が Queue と同名の Bind が作成されています。
ちなみに、空文字列の Exchange は、RabbitMQ 起動時から存在しており、タイプは direct です。
Client 側
主要箇所を抜粋した Client 側のコードは、下記の通りです。
これを、client.pl という名前で保存しておきます。
# Server から Response を受け取るための、一時的な Queue を用意します。 # Queue 名を指定していないため、RabbitMQ が一意な名前を割り当てます。 # exclusive オプションを付ける事により、他の Client は利用できない Queue が作成されます。 # また、exclusive オプションを付けられた Queue は、Client が Rabbit MQ から切断された時点で、自動的に削除されます。 my $queue = $rf->declare_queue({ exclusive => 1 })->method_frame->queue; # Server へ 'Hello' を送ります。 # reply_to に、Response を受けるための Queue の名前を指定します。 $rf->publish( {routing_key => 'test_q'}, {reply_to => $queue}, 'Hello', ); # Consume を開始します。 $rf->consume({ queue => $queue, }); # Server からの Response を受け取ります。 my $response = $rf->poll(); # Server から受け取った Response を表示します。 print $response->{body}->payload, "\n";
実際には、RabbitMQ への connect/disconnect 処理が必要ですが、割愛します。
Server 側
主要箇所を抜粋した Server 側のコードは、下記の通りです。
これを、server.pl という名前で保存しておきます。
# Consume を開始します。 $rf->consume({ queue => 'test_q', }); while (1) { # Client からの Request を受け取ります。 my $request = $rf->poll(); # Request から、返信先の Queue 名と Body を取り出します。 my $queue = $request->{header}->header_frame->reply_to; my $body = $request->{body}->payload; # Client へ Response を送ります。 $rf->publish( {routing_key => $queue}, {}, sprintf('%s(%d)', $body, $$), ); }
試してみる
負荷分散を考慮し、Server を二つ起動します。
% /path/to/server.pl & [1] 36044 % /path/to/server.pl & [2] 36069
Client から Server へ Request を送ります。
% /path/to/client.pl Hello(36044) % /path/to/client.pl Hello(36069) % /path/to/client.pl Hello(36044)
Response を返す Server プロセスが交互に入れ替わっています。
便利ですねー。念のため補足しておくと、Client-Server モデルは、数ある RabbitMQ の利用方法のうちの一つでしかありません。