ここでは、AMQPプロトコルが「内部で」何を行うかについての概念的な理解が役立ちます。AMQP 0.9.1がデプロイすることを選択したドキュメントとAPIはこれを特に混乱させるので、質問自体は多くの人々が取り組む必要のある問題です。
TL; DR
接続は、 AMQPサーバと物理的に交渉TCPソケットです。適切に実装されたクライアントは、アプリケーションごとにこれらの1つを持ち、スレッドセーフであり、スレッド間で共有できます。
チャネルは、接続上の単一のアプリケーションセッションです。スレッドには、これらのセッションが1つ以上含まれます。AMQPアーキテクチャ0.9.1は、これらがスレッド間で共有されないことであり、それを作成したスレッドが終了したら、閉じる/破棄する必要があります。また、さまざまなプロトコル違反が発生すると、サーバーによって閉じられます。
消費者は、特定のチャネル上の「メールボックス」の存在を表す仮想構築物です。コンシューマーの使用は、特定のキューからそのチャネルエンドポイントにメッセージをプッシュするようブローカーに指示します。
接続の事実
まず、他の人が正しく指摘しているように、接続はサーバーへの実際のTCP接続を表すオブジェクトです。接続はAMQPのプロトコルレベルで指定され、ブローカーとのすべての通信は1つ以上の接続を介して行われます。
- これは実際のTCP接続であるため、IPアドレスとポート番号があります。
- プロトコルパラメータは、接続の設定(ハンドシェイクと呼ばれるプロセス)の一部としてクライアントごとにネゴシエートされます。
- それは長持ちするように設計されています。接続のクローズがプロトコル設計の一部であるケースはほとんどありません。
- OSIの観点から、それはおそらくレイヤー6のどこかに存在します
- ハートビートは、接続ステータスを監視するように設定できます。TCP自体には、これを行うためのものが含まれていないためです。
- 基になるTCPソケットへの読み取りと書き込みを管理する専用スレッドを用意するのが最善です。すべてではないにしても、ほとんどの場合、RabbitMQクライアントがこれを行います。その点で、それらは一般的にスレッドセーフです。
- 比較的言えば、接続は(ハンドシェイクのため)作成するのに「高価」ですが、実際には、これは本当に重要ではありません。ほとんどのプロセスは実際には1つの接続オブジェクトのみを必要とします。ただし、単一のスレッド/ソケットが提供できるよりも高いスループットが必要であることがわかった場合は、プール内で接続を維持できます(現在のコンピューティングテクノロジーでは不可能です)。
チャンネルの事実
A チャンネルのRabbitMQブローカーと通信するためのアプリの各部分のために開かれたアプリケーションセッションです。単一の接続で動作し、ブローカーとのセッションを表します。
- アプリケーションロジックの論理部分を表すため、通常、各チャネルは独自のスレッドに存在します。
- 通常、アプリによって開かれたすべてのチャネルは単一の接続を共有します(それらは接続の上で動作する軽量セッションです)。接続はスレッドセーフなので、これで問題ありません。
- ほとんどのAMQP操作はチャネルを介して行われます。
- OSIレイヤーの観点からすると、チャネルはおそらくレイヤー7の周りにあります。
- チャネルは一時的なものとして設計されています。AMQPの設計の一部は、通常、エラーに応答してチャネルが閉じられることです(たとえば、既存のキューを削除する前に、異なるパラメーターでキューを再宣言するなど)。
- それらは一時的であるため、チャネルはアプリによってプールされるべきではありません。
- サーバーは整数を使用してチャネルを識別します。接続を管理するスレッドは、特定のチャネルのパケットを受信すると、この番号を使用して、パケットが属するチャネル/セッションをブローカーに通知します。
- チャネルは、スレッド間で共有しても意味がないため、一般にスレッドセーフではありません。ブローカーを使用する必要がある別のスレッドがある場合は、新しいチャネルが必要です。
消費者情報
コンシューマーは、AMQPプロトコルによって定義されたオブジェクトです。これはチャネルでも接続でもなく、特定のアプリケーションがメッセージをドロップするための一種の「メールボックス」として使用するものです。
- 「コンシューマーの作成」とは、ブローカーに(接続を介したチャネルを使用して)メッセージをそのチャネル経由でプッシュすることを通知することを意味します。それに応じて、ブローカーはチャンネルにコンシューマーがいることを登録し、メッセージをプッシュし始めます。
- 接続を介してプッシュされる各メッセージは、チャネル番号とコンシューマー番号の両方を参照します。このようにして、接続管理スレッド(この場合はJava API内)はメッセージの処理方法を認識します。その後、チャネル処理スレッドはメッセージの処理方法も認識します。
- 文字どおりアプリケーション固有であるため、コンシューマの実装には最も大きな変動があります。私の実装では、コンシューマー経由でメッセージが到着するたびにタスクをスピンオフすることを選択しました。したがって、私は、接続を管理するスレッド、チャネル(さらにはコンシューマー)を管理するスレッド、そしてコンシューマーを介して配信されるメッセージごとに1つ以上のタスクスレッドを持っていました。
- 閉会の接続は、接続上のすべてのチャネルを閉じます。閉会チャネルは、チャネル上のすべての消費者を閉じます。(チャンネルを閉じずに)コンシューマをキャンセルすることもできます。3つのことのいずれかを実行することが理にかなっている場合は、さまざまな場合があります。
- 通常、AMQPクライアントでのコンシューマーの実装は、他のスレッドまたはコード(発行を含む)のアクティビティとの競合を回避するために、1つの専用チャネルをコンシューマーに割り当てます。
コンシューマースレッドプールの意味については、Javaクライアントが、クライアントが実行するようにプログラムしたものと同様のことをしていると思います(私は.Netクライアントに基づいていますが、大幅に変更されています)。