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 の利用方法のうちの一つでしかありません。