キュー ベースの負荷平準化パターン

Azure Functions
Azure Service Bus

タスクとそれによって呼び出されるサービスとの間のバッファーとして機能するキューを使用して、サービスの失敗やタスクのタイムアウトの原因となり得る断続的な高負荷を平準化します。これは、需要のピークによってタスクとサービスの両方の使用可能性と応答性が受ける影響を最小限に抑えるうえで役立つ場合があります。

コンテキストと問題

クラウド内の多くのソリューションでは、サービスを呼び出すタスクを実行する必要があります。 この環境では、サービスに断続的に大きい負荷がかかると、パフォーマンスまたは信頼性の問題が発生する場合があります。

サービスはそのサービスを使用するタスクと同じソリューションの一部である場合や、キャッシュまたはストレージ サービスなどの頻繁に使用されるリソースへのアクセスを提供するサードパーティのサービスである場合があります。 同じサービスが同時に実行されている多数のタスクで使用されると、サービスに対する要求のボリュームを常に予測するのが困難になる場合があります。

サービスの需要がピークに達する可能性があります。その場合、過負荷となり、適時に要求に応答できなくなります。 多数の同時要求がサービスに殺到すると、これらの要求が原因の競合を処理できない場合にサービス障害が発生することもあります。

解決策

ソリューションをリファクタリングし、タスクとサービス間でキューを導入します。 タスクとサービスを非同期に実行します。 タスクは、キューにサービスで必要なデータを含むメッセージを投稿します。 キューは、サービスが取得するまでメッセージを格納するバッファーとして機能します。 サービスはキューからメッセージを取得して処理します。 さまざま速度で生成可能な、多数のタスクからの要求は、同じメッセージ キューを通じてサービスに渡すことができます。 以下の図は、キューを使用したサービス負荷の平準化を示しています。

図 1 - キューを使用したサービス負荷の平準化

キューはサービスからタスクを切り離すため、サービスは、同時タスクからの要求のボリュームに関係なく、独自のペースでメッセージを処理できます。 また、サービスがキューにメッセージを投稿したときに使用できない場合でも、タスクの遅延は発生しません。

このパターンには次のような利点があります。

  • サービスで発生する遅延がすぐにアプリケーションに直接影響することはないため、可用性を最大化するのに役立ちます。サービスが使用できない場合や、現在、メッセージを処理していない場合であっても、キューにメッセージを継続的に投稿できます。

  • 需要を満たすためにキューの数とサービスの数の両方を変更できるため、スケーラビリティを最大化するのに役立ちます。

  • ピーク時の負荷ではなく、平均負荷に対応するのに十分な数のサービス インスタンスをデプロイするだけでよいため、コスト管理に役立ちます。

    一部のサービスでは、それを超えるとシステムで障害が発生する可能性があるしきい値に需要が達した場合に、スロットルを実装します。 スロットルにより使用可能な機能を減らすことができます。 このしきい値に達しないように、これらのサービスの負荷を平準化することができます。

問題と注意事項

このパターンの実装方法を決めるときには、以下の点に注意してください。

  • ターゲット リソースが過多にならないように、サービスによるメッセージの処理速度を制御するアプリケーション ロジックを実装する必要があります。 システムの次のステージで需要が急増しないようにしてください。 負荷がかかっているシステムをテストし、必要な平準化が行われることを確認し、キューの数とメッセージを処理するサービス インスタンスの数を調整してください。
  • メッセージ キューは一方向の通信メカニズムです。 タスクがサービスからの応答を予期している場合、サービスが応答を送信するために使用できるメカニズムを実装する必要がある場合があります。 詳細については、「非同期メッセージングの基本」を参照してください。
  • キューで要求をリッスンしているサービスに自動スケールを適用する場合は注意してください。 これにより、サービスが共有するすべてのリソースの競合が増え、負荷を平準化するためのキューの使用効果が弱まる場合があります。
  • サービスの負荷によっては、処理する以上の要求がシステムで常にキューに入れられ、実質的に常に後続処理が行われる状況が発生する場合があります。 アプリケーションへの受信トラフィックの変動性を考慮する必要があります
  • このパターンでは、キューの永続性によって情報が失われる可能性があります。 (システムの制限により) キューがクラッシュしたり情報が失われたりした場合、確実な配信が得られない可能性があります。 ソリューションのニーズに基づいて、キューの動作とシステムの制限を考慮する必要があります。

このパターンを使用する状況

このパターンは、過負荷になる可能性のあるサービスを使用するすべてのアプリケーションに有効です。

アプリケーションが最短の待機時間でサービスからの応答を予期している場合、このパターンは有効ではありません。

ワークロード設計

設計者は、Azure Well-Architected Framework の柱で説明されている目標と原則に対処するために、ワークロードの設計でどのようにキュー ベースの負荷平準化パターンを使用できるかを評価する必要があります。 次に例を示します。

重要な要素 このパターンが柱の目標をサポートする方法
信頼性設計の決定により、ワークロードが誤動作に対して復元力を持ち、障害発生後も完全に機能する状態に回復することができます。 このパターンで記述されるアプローチでは、タスクの到着をタスクの処理から切り離すことで、需要の急増に対する回復性を提供できます。 また、キュー処理の誤動作を分離して、取り込みに影響を与えないようにすることもできます。

- RE:06 スケーリング
- Re: 07バックグラウンドジョブ
コスト最適化は、ワークロードの投資収益率の維持と改善に重点を置いています。 要求やタスクの取り込みと負荷処理が分離されているため、このアプローチを使用すると、ピーク時の負荷を処理するためのリソースをオーバープロビジョニングする必要を軽減できます。

- CO:12 スケーリング コスト
パフォーマンスの効率化は、スケーリング、データ、コードを最適化することによって、ワークロードが効率的にニーズを満たすのに役立ちます。 このアプローチでは、要求の取り込みが要求の処理速度と相関していなくてもかまわないため、スループットのパフォーマンスを意図的に設計できます。

- PE:05 スケーリングとパーティショニング

設計決定と同様に、このパターンで導入される可能性のある他の柱の目標とのトレードオフを考慮してください。

Web アプリでは、外部データ ストアにデータを書き込みます。 Web アプリの多くのインスタンスが同時に実行されている場合、データ ストアでは要求に迅速に応答できない可能性があります。これにより、要求がタイムアウトになるか、調整されるか、それ以外の場合は失敗します。 以下の図は、アプリケーションのインスタンスからの多くの同時要求がデータ ストアに殺到している様子を示しています。

図 2 - Web アプリのインスタンスからの多くの同時要求がサービスに殺到している様子

これを解決するために、キューを使用して、アプリケーション インスタンスとデータ ストア間の負荷を平準化することができます。 Azure 関数アプリではメッセージをキューから読み取り、データ ストアへの読み取り/書き込み要求を実行します。 関数アプリのアプリケーション ロジックでは、データ ストアの過負荷を防ぐために、データ ストアに要求を渡す速度を制御できます (それ以外の場合、関数アプリではバック エンドで同じ問題が再発するだけです)。

図 3 - キューと関数アプリを使用した負荷の平準化

次のステップ

このパターンを実装する場合は、次のガイダンスも関連している可能性があります。

  • 非同期メッセージングの基本。 メッセージ キューでは本質的に非同期です。 サービスとの直接通信からメッセージ キューの使用にまで適応される場合は、タスクでアプリケーション ロジックを再設計する必要がある可能性があります。 同様に、メッセージ キューからの要求を受け入れるためにサービスをリファクタリングする必要がある場合があります。 例に示されているように、プロキシ サービスを実装できる場合もあります。

  • Azure メッセージング サービスの選択。 Azure アプリケーションのメッセージングおよびキューイング メカニズムの選択に関する情報です。

  • メッセージベースの非同期通信

  • Web/キューワーカー アーキテクチャ スタイル。 Web とワーカーはいずれもステートレスです。 セッション状態は、分散キャッシュに格納することができます。 ワーカーによる実行時間の長い作業は、非同期的に実行されます。 ワーカーは、キューのメッセージによってトリガーされるか、またはバッチ処理のためにスケジュールに従って実行できます。

このパターンを実装する場合は、次のパターンも関連している可能性があります。

  • 競合コンシューマー パターン。 それぞれが負荷平準化キューのメッセージ コンシューマーとして機能する、サービスの複数のインスタンスを実行できる場合があります。 この方法を使用して、メッセージを受信してサービスに渡す速度を調整することができます。

  • スロットル パターン。 サービスでスロットルを実装する簡単な方法は、キュー ベースの負荷平準化を使用し、メッセージ キューを通じてすべての要求をサービスにルーティングすることです。 サービスは、必要なリソースを使い切らない速度で要求を処理し、発生する可能性のある競合量を減らすことができます。