RabbitMQ とは
クラウドネイティブ アプリでは、マイクロサービスは、ユーザーに応答するために必要なすべての情報を取得するために通信する必要があります。 このメッセージングは、コンポーネント間にネットワークの問題や障害が発生した場合でも堅牢である必要があります。 RabbitMQ は、メッセージングの信頼性を高めるために使用できる 1 つのツールです。
あなたのアウトドア用品店では、マイクロサービス化を急速に進めています。 しかし、アプリケーションのテストでは、あるマイクロサービスから別のマイクロサービスへの呼び出しが一部失われている可能性が判明しました。 会社の評判に関わる運用環境では、この問題が発生しないようにする必要があります。
このユニットでは、RabbitMQ を使用してマイクロサービス向けの柔軟で回復性がある通信プラットフォームを作成する方法について説明します。
クラウドネイティブ アプリでメッセージ ブローカーを使用する理由
クラウドネイティブ アプリは独立したマイクロサービスで構成されており、多くの場合、それらは別々のチームによって構築され、使用されているテクノロジや言語が異なります。 各チームには独自の開発スプリントとアップグレード スケジュールがあり、修正や新機能を継続的にデプロイできます。 ただし、ユーザーから要求が届くと、それを受信するマイクロサービスは、完全な応答を作成するために、ほとんどの場合、他のマイクロサービスとバッキング サービスを呼び出し、それらからの応答を受信する必要があります。
当然、これらのサービス間の要求および応答の形式とスキーマは、開発チーム間で合意する必要があり、めったに変更することはできません。 これらは通常、REST API として実装されます。 既存のメソッドやパラメーターを変更せずに、各インターフェースの新しい機能を優先的に実装する必要があります。 ただし、マイクロサービスが直接通信することを選択した場合、次のような問題が発生する可能性があります。
- 宛先マイクロサービスがオフラインまたはビジー状態の場合、そのマイクロサービスに送信されたメッセージはどうなるでしょうか? メッセージが失われた場合、その結果はどうなるでしょうか?
- 同じメッセージを複数の宛先に送信するにはどうすればよいでしょうか?
- マイクロサービスが複数のコンテナーで実行されている場合、どのコンテナーにメッセージを送信すればよいでしょうか?
メッセージ ブローカーは、これらの問題に対処するミドルウェアです。 サービスは、メッセージを宛先に直接送信しないで、メッセージ ブローカーに送信します。 ブローカーは、メッセージを到着順にキューに格納します。 宛先サービスはこれらのキューをサブスクライブし、メッセージを一度に 1 つずつ取得して処理します。
宛先サービスが利用できない場合でも、送信側のマイクロサービスはメッセージをキューに配置できます。 宛先サービスが再起動すると、メッセージはキューの同じポイントから引き続き取得されます。 送信側の待機時間は長くなりますが、メッセージが失われることはありません。
複数の宛先がキューをサブスクライブできるため、1 つのメッセージを複数のマイクロサービスで受信できます。 さらに、複数のコンテナーが単一のマイクロサービスのインスタンスをホストしている場合、最初に使用可能になったインスタンスがメッセージを取得します。 ブローカーは、メッセージをインスタンスに自動的に分散して、負荷を分散します。
RabbitMQ とは
RabbitMQ は、最も人気のあるメッセージ ブローカーであり、RabbitMQ がクラウドネイティブ アプリでの通信処理に最適な候補とされる多くの機能を備えています。 次の情報が含まれます。
- キューをホストする RabbitMQ サーバー。 このサーバーは、高可用性のためのクラスタリングとフェールオーバーをサポートし、コンテナーで実行できます。
- Advanced Message Queuing Protocol (AMQP)、Simple Text Oriented Message Protocol (STOMP)、Message Queuing Telemetry Transport (MQTT) の実装。
- .NET、Java、Erlang で使用できる AMQP クライアント ライブラリ。
RabbitMQ の概念
RabbitMQ の用語では、メッセージを送受信するマイクロサービスはクライアントです。 メッセージを送信するクライアントは、メッセージ プロデューサーと呼ばれます。 メッセージを受信するクライアントは、メッセージ コンシューマーです。 RabbitMQ サービスは、メッセージ ブローカーです。
メッセージの送信方法
RabbitMQ は汎用性が高く、さまざまなキューイング モデルを実装できます。 いくつかの一般的なパターンを調べてみましょう。
プロデューサーとコンシューマーが 1 つずつある場合、使用されるキューは 1 つで、すべてのメッセージは同じ宛先に届きます。 この単純な構成でも、停止に円滑に対処できる堅牢なメッセージング システムを構築する必要があります。
競合コンシューマーへのメッセージの送信
競合コンシューマー モデルでは、プロデューサーはメッセージを 1 つの作業キューに送信します。 2 つ以上のコンシューマーがキューからメッセージを取得します。 各メッセージを取得できるコンシューマーは 1 つのみであるため、コンシューマーはメッセージの取得をめぐって競合します。
このパターンは、クラウドネイティブ アプリで、容量を増やすためにコンシューマーのマイクロサービスが複数のコンテナーでホストされている場合に役立ちます。 各メッセージはコンシューマーの 1 つのインスタンスにのみ到達するため、1 回だけ処理されます。 作業は重複しません。
発行とサブスクライブ
プロデューサーから複数のコンシューマーに 1 つのメッセージを送信する場合、発行/サブスクライブ モデルを使用します。 プロデューサーは、メッセージを交換に送信します。 各コンシューマーは、その交換からメッセージをサブスクライブします。 コンシューマーがサブスクライブすると、RabbitMQ によって、そのサブスクリプション用の新しい作業キューが作成されます。 各メッセージはその交換のすべてのキューにコピーされ、サブスクライブしているすべてのコンシューマーによって受信されます。 コンシューマーが各メッセージをめぐって競合することはありません。 代わりに、すべてのコンシューマーが各メッセージのコピーを受信します。
発行/サブスクライブ モデルでは、ファンアウト交換を使用します。これは、すべてのメッセージをすべての作業キューにコピーします。
このパターンは、各メッセージを複数のマイクロサービスで処理する場合に役立ちます。 たとえば、顧客がカートをチェックアウトするときに、購入された各製品の数に関するメッセージを送信するとしましょう。 このメッセージは、小包を梱包するように倉庫に指示する出荷マイクロサービスと、在庫数を減らしてサプライヤーへの注文をトリガーする在庫マイクロサービスの両方に届ける必要があります。
メッセージとトピックのルーティング
1 つのメッセージを複数のコンシューマーに配信しますが、各コンシューマーにフィルターを適用することが必要な場合があります。 このパターンは、メッセージ ルーターと呼ばれます。 発行/サブスクライブ モデルと同様に、コンシューマーは交換にサブスクライブして複数の作業キューを作成します。 ただし、このモデルでは、ファンアウト交換ではなく 直接交換を使用します。 この交換を使用する場合、各サブスクリプションにはバインディング キーがあります。 サブスクリプションには、ルーティング キーがそのバインディング キーと一致するメッセージのみが送信されます。 他のメッセージは除外されます。
このパターンは、一部のコンシューマーがメッセージ ストリームのサブセットのみを処理する必要がある場合に役立ちます。 たとえば、エラーが発生したときにメッセージを送信するマイクロサービスがあるとしましょう。 すべてのエラーは、ログ マイクロサービスに送信する必要があります。 重大なエラーは管理マイクロサービスに送信して、エンジニアに問題を修正するように警告する必要があります。
直接交換では、1 つの基準に基づいてメッセージがルーティングされます。 柔軟性をさらに高めるには、トピック交換を使用できます。 メッセージごとに、複数の用語をドットで区切ったルーティング キーを使用できます。 バインディング キーでは、ワイルド カード * を使用して 1 つの単語だけを置き換えるか、# を使用して 0 個以上の単語を置き換えることができます。
Note
RabbitMQ の代替としては、Apache Kafka と Azure Service Bus があります。 これらのメッセージ ブローカーは両方とも、.NET Aspire 内の専用コンポーネントによってサポートされます。 Azure Service Bus については、このラーニング パスの後のモジュールで学習します。