次の方法で共有


競合コンシューマー パターン

複数の同時実行コンシューマーが、同じメッセージング チャネルで受信したメッセージを処理できるようにします。 複数の同時コンシューマーがある場合、システムは複数のメッセージを同時に処理してスループットを最適化し、スケーラビリティと可用性を向上させ、ワークロードのバランスを取ることができます。

コンテキストと問題

クラウド アプリケーションは、多くの場合、多数の要求を処理します。 アプリケーションは、各要求を同期的に処理する代わりに、メッセージング システムを介して要求を非同期的に処理するコンシューマー サービスに渡すことができます。 この戦略は、要求処理がアプリケーションのビジネス ロジックをブロックするのを防ぐのに役立ちます。

要求の数は、時間の経過と同時に大きく異なる場合があります。 ユーザー アクティビティが急激に増加したり、複数のテナントからの要求が集計されたりすると、予測できないワークロードが発生する可能性があります。 ピーク時には、システムが 1 秒あたり何百もの要求を処理する必要がある場合があります。 それ以外の場合は、数値が小さい場合があります。 また、これらの要求を処理するために必要な作業は大きく異なる場合があります。 1 つのコンシューマー サービス インスタンスを使用すると、要求がそのインスタンスを圧倒する可能性があります。 または、アプリケーション メッセージが急増すると、メッセージング システムが過負荷になる可能性があります。

この変動するワークロードを処理するために、システムは複数のコンシューマー サービス インスタンスを実行できます。 ただし、システムは、各メッセージが 1 つのコンシューマーにのみ配信されるように、これらのコンシューマーを調整する必要があります。 また、1 つのインスタンスがボトルネックにならないように、システムはコンシューマー間でワークロードのバランスを取る必要があります。

ソリューション

メッセージ キューを使用して、アプリケーションとコンシューマー サービス インスタンスの間の通信チャネルを実装します。 アプリケーションはキューにメッセージとして要求を投稿し、コンシューマー サービス インスタンスはキューからメッセージを受信して処理します。 この方法により、コンシューマー サービス インスタンスの同じプールで、アプリケーションの任意のインスタンスからのメッセージを処理できます。 次の図は、メッセージ キューがサービス インスタンスに動作を分散する方法を示しています。

メッセージ キューがサービス インスタンスに動作を分散する方法を示す図。

複数のコンシューマーがこれらのメッセージを受信しますが、競合コンシューマー パターンは Publisher-Subscriber パターンとは異なります。 競合コンシューマー パターンでは、1 つのコンシューマーが処理のために各メッセージを受信します。 Publisher-Subscriber パターンでは、 すべての コンシューマー がすべての メッセージを受信します。

このソリューションには次の利点があります。

  • これは、アプリケーション インスタンスからの要求ボリュームの幅広いバリエーションを処理できる負荷平準化システムを提供します。 キューは、アプリケーション インスタンスとコンシューマー サービス インスタンスの間のバッファーとして機能します。 このバッファーにより、アプリケーション インスタンスとサービス インスタンスの両方の可用性と応答性への影響を最小限に抑えることができます。 詳細については、「キュー ベースの負荷平準化パターン」を参照してください。 実行時間の長い処理を必要とするメッセージでは、他のコンシューマー サービス インスタンスが他のメッセージを同時に処理することを妨げることはありません。

  • そのため、信頼性が向上します。 プロデューサーがこのパターンを使用する代わりにコンシューマーと直接通信し、コンシューマーを監視しない場合、コンシューマーが失敗したときにメッセージが失われ、処理に失敗する可能性が高くなります。 このパターンでは、システムは特定のサービス インスタンスにメッセージを送信しません。 失敗したサービス インスタンスはプロデューサーをブロックせず、稼働中のサービス インスタンスはメッセージを処理できます。

  • コンシューマー間、またはプロデューサーとコンシューマー インスタンスの間で複雑な調整を行う必要はありません。 メッセージ キューによって、各メッセージは少なくとも 1 回は配信されます。

  • スケーリングします。 自動スケールを適用すると、メッセージ ボリュームの変動に応じて、コンシューマー サービス インスタンスの数を動的に増減できます。

  • メッセージ キューでトランザクションの読み取り操作を提供する場合、回復性を改善できます。 コンシューマー サービス インスタンスがトランザクション操作の一部としてメッセージを読み取って処理し、失敗した場合、このパターンによってメッセージがキューに返され、別のコンシューマー サービス インスタンスで処理できるようになります。 メッセージが継続的に失敗するリスクを軽減するには、 配信不能キューを使用することをお勧めします。

問題と考慮事項

このパターンを実装する方法を決定するときは、次の点を考慮してください。

  • メッセージの順序: コンシューマー サービス インスタンスがメッセージを受信する順序は保証されず、メッセージが作成された順序が必ずしも表示されるとは限りません。 メッセージをべき等に処理するようにシステムを設計する。 この設計は、処理順序の依存関係を排除するのに役立ちます。

    Azure Service Bus では、 メッセージ セッションを使用して、メッセージやその他のパターンの先入れ先出し順序を保証できます。

  • サービスの回復性の要件: システムが失敗したサービス インスタンスを検出して再起動する場合は、1 つのメッセージを複数回取得して処理するときの影響を最小限に抑えるために、それらのサービス インスタンスがべき等として実行する操作を実装することが必要になる場合があります。

  • 有害メッセージ検出: 不正な形式のメッセージや、使用できないリソースへのアクセスを必要とするタスクは、サービス インスタンスが失敗する可能性があります。 システムは、これらのメッセージが無期限にキューに戻らないようにし、代わりに詳細をキャプチャして他の場所に保存して、必要に応じて分析する必要があります。 Service Bus は、配信カウントが構成されたしきい値を超えた後、デッドレターキューにメッセージを自動的に送信できます。

  • 結果の処理: メッセージを処理するサービス インスタンスは、メッセージを生成するアプリケーション ロジックから完全に切り離されているため、直接通信できない可能性があります。 サービス インスタンスがアプリケーション ロジックに戻る必要がある結果を生成する場合は、両方のコンポーネントがアクセスできる場所にこの情報を格納します。 アプリケーション ロジックが不完全なデータを取得しないようにするには、処理が完了した時点をシステムが示す必要があります。 ワーカー プロセスは、専用のメッセージ応答キューを介してアプリケーション ロジックに結果を返すことができます。 アプリケーション ロジックで、このような結果を元のメッセージと関連付けられる必要があります。

  • メッセージング システムのスケーリング: 大規模なソリューションでは、メッセージの量が多い場合、1 つのメッセージ キューが過剰になり、システムのボトルネックになる可能性があります。 このような場合は、メッセージング システムをパーティション分割して特定のプロデューサーから特定のキューにメッセージを送信するか、負荷分散して複数のメッセージ キューにメッセージを分散することを検討してください。

  • メッセージング システムの信頼性: 信頼できるメッセージング システムを使用して、アプリケーションがメッセージをエンキューした後にメッセージが失われないことを保証します。 この機能は、すべてのメッセージが少なくとも 1 回配信されるようにするために不可欠です。

このパターンを使用する場合

このパターンは次の状況で使用します。

  • アプリケーション ワークロードは、非同期的に実行できるタスクに分かれています。

  • タスクは独立しており、並列して実行できます。

  • 作業量は非常に可変であり、スケーラブルなソリューションが必要です。

  • このソリューションは高可用性を提供し、タスク処理が失敗しても回復性を維持する必要があります。

このパターンは、次の場合に適さない場合があります。

  • アプリケーション ワークロードを個別のタスクに簡単に分離したり、タスク間の依存関係を高くしたりすることはできません。

  • タスクは同期的に実行する必要があり、アプリケーション ロジックは各タスクが完了するまで待機してから続行する必要があります。

  • タスクは特定のシーケンスで実行する必要があります。

一部のメッセージング システムでは、プロデューサーがメッセージをグループ化し、同じコンシューマーがグループ内のすべてのメッセージを処理できるようにするセッションがサポートされています。 このメカニズムは、メッセージの順序付けを強制し、プロデューサーから単一のコンシューマーに順番にメッセージを配信するためにサポートされている場合に、優先順位付けされたメッセージと共に使用できます。

ワークロード設計

ワークロードの設計で競合コンシューマー パターンを使用して、 Azure Well-Architected Framework の柱で説明されている目標と原則に対処する方法を評価します。 次の表は、このパターンが各柱の目標をサポートする方法に関するガイダンスを示しています。

支柱 このパターンが柱の目標をサポートする方法
信頼性設計の決定は、故障に対するワークロードの回復性を高め、障害の発生後にワークロードを完全な機能状態に回復させるために役立ちます。 このパターンは、ユーザーをレプリカとして扱うことによってキュー処理の冗長性を構築するため、インスタンス障害が発生しても他のユーザーがキューメッセージを処理できなくなることはありません。

- RE: 05冗長性
- バックグラウンド ジョブ
コストの最適化では、ワークロードの投資収益率維持と向上に重点を置いています。 このパターンは、キューの深さに基づいてスケーリングされ、キューが空の場合はゼロにスケールダウンできるため、コストを最適化するのに役立ちます。 同時コンシューマー インスタンスの最大数を制限できるため、コストを最適化することもできます。

- CO:05 レート最適化
- CO:07 コンポーネントコスト
パフォーマンス効率 は、スケーリング、データ、およびコードの最適化を通じて、ワークロード の需要を効率的に満たすのに役立ちます。 このパターンでは、使用率を高めるためにコンシューマー ノード間で負荷が分散され、キューの深さに基づく動的スケーリングによってオーバープロビジョニングが最小限に抑えられます。

- PE:05 スケーリングとパーティショニング
- PE:07 コードとインフラストラクチャ

このパターンによって柱内にトレードオフが生じる場合は、他の柱の目標に照らして検討してください。

Azure には、このクラウド設計パターンを直接実装する Service Bus キューと Azure Functions キュー トリガーが用意されています。 関数は、トリガーとバインドを介して Service Bus と統合されます。 この統合により、パブリッシャーからのキュー メッセージを使用する関数を構築できます。 アプリケーションを発行するとメッセージがキューにポストされ、Functions として実装されたコンシューマーはそれらのメッセージを取得して処理できます。

回復性のために、Service Bus キューを使用すると、コンシューマーはキューからメッセージを取得するときに PeekLock モード を使用できます。 このモードではメッセージは保持されますが、他のコンシューマーからは非表示になります。 Functions ランタイムは、PeekLock モードでメッセージを受信します。 関数が正常に完了すると、ランタイムはメッセージに対して Complete を呼び出します。 関数が失敗した場合、ランタイムは Abandon を呼び出し、メッセージをもう一度表示して、別のコンシューマーがメッセージを取得できるようにする可能性があります。 関数が PeekLock タイムアウトより長く実行される場合、ランタイムは関数が実行されている限りロックを自動的に更新します。

Service Bus を使用して関数に作業を分散する図。

関数は、 キューの深さとトラフィックに基づいてコンシューマー インスタンスの数を自動的にスケーリングします。 このスケーリングにより、ソリューションは少量の期間中にコストを最小限に抑えながら、作業のバーストを処理できます。 Functions が複数のインスタンスを作成する場合、メッセージを個別にプルして処理することで競合します。 詳細については、「Service Bus キュー、トピック、サブスクリプション」および「関数の Service Bus トリガー」を参照してください。

.NET 用 Service Bus クライアント ライブラリを使用して Service Bus キューにメッセージを送信する方法の詳細については、公開されている を参照してください。

次のステップ

  • Azure でメッセージング サービスを選択する: Service Bus、Azure Storage キュー、Azure Event Hubs、Azure Event Grid などのさまざまな Azure メッセージング サービスが非同期通信パターンをサポートする方法と、シナリオに適したサービスとメッセージング モデルを選択する方法について説明します。

  • 自動スケールのベスト プラクティス: アクティビティが少ない期間中にピーク時の負荷と制御コストを処理できるように、キューの長さやメッセージのスループットなど、ワークロードに基づいてコンシューマー インスタンスをスケールアウトするソリューションを設計する方法について説明します。

  • コンピューティング リソース統合パターン: コンシューマー サービスの複数のインスタンスを 1 つのプロセスに統合して、コストと管理オーバーヘッドを削減できる場合があります。 コンピューティング リソース統合パターンでは、このアプローチの利点とトレードオフについて説明します。

  • キュー ベースの負荷平準化パターン: メッセージ キューは、システムに回復性を追加できます。 回復性により、サービス インスタンスは、アプリケーション インスタンスからのさまざまな量の要求を処理できます。 メッセージ キューは、負荷を平準化するバッファーとして機能します。 「Queue-based Load Leveling pattern」(キューベースの負荷平準化パターン) では、このスキーマについて詳しく説明しています。