多くの種類のアプリケーションでは、ユーザー インターフェイス (UI) とは別に実行されるバックグラウンド タスクが必要です。 たとえば、バッチ ジョブ、集中的な処理タスク、ワークフローなどの実行時間の長いプロセスなどがあります。 バックグラウンド ジョブは、ユーザーの操作を必要とせずに実行できます。アプリケーションはジョブを開始し、ユーザーからの対話型要求の処理を続行できます。 これにより、アプリケーション UI の負荷を最小限に抑えることができます。これにより、可用性が向上し、対話型の応答時間が短縮されます。
たとえば、ユーザーがアップロードした画像のサムネイルを生成するアプリケーションが必要な場合は、バックグラウンド ジョブとしてこれを行い、完了したときにサムネイルをストレージに保存できます。ユーザーはプロセスが完了するのを待つ必要はありません。 同様に、注文を行うユーザーは、注文を処理するバックグラウンド ワークフローを開始できますが、UI を使用すると、ユーザーは引き続き Web アプリを参照できます。 バックグラウンド ジョブが完了すると、保存されている注文データを更新し、注文を確認する電子メールをユーザーに送信できます。
タスクをバックグラウンド ジョブとして実装するかどうかを検討する場合、主な条件は、タスクをユーザーの操作なしで実行できるかどうか、および UI がジョブが完了するのを待つ必要がないかどうかです。 ユーザーまたは UI が完了するまで待機する必要があるタスクは、バックグラウンド ジョブとして適切でない場合があります。
バックグラウンド ジョブの種類
バックグラウンド ジョブには、通常、次の種類のジョブが 1 つ以上含まれます。
- 数学的計算や構造モデル分析などの CPU 負荷の高いジョブ。
- 一連のストレージ トランザクションの実行やファイルのインデックス作成など、I/O 集中型ジョブ。
- 夜間のデータ更新やスケジュールされた処理などのバッチ ジョブ。
- 長時間にわたって実行されるワークフローとして、注文の処理やサービスおよびシステムのプロビジョニングがあります。
- タスクが処理のためにより安全な場所に渡される機密データ処理。 たとえば、Web アプリ内で機密データを処理したくない場合があります。 代わりに、 Gatekeeper パターン などのパターンを使用して、保護されたストレージにアクセスできる分離されたバックグラウンド プロセスにデータを転送できます。
トリガー (条件や動作を引き起こすもの)
バックグラウンド ジョブは、いくつかの異なる方法で開始できます。 これらは、次のいずれかのカテゴリに分類されます。
- イベント ドリブン トリガー。 タスクは、イベント (通常はユーザーまたはワークフロー内のステップによって実行されるアクション) に応答して開始されます。
- スケジュール駆動トリガー。 タスクはタイマーに基づいて呼び出されます。 これは、定期的なスケジュールまたは後で指定される 1 回限りの呼び出しです。
イベント駆動型トリガー
イベント ドリブン呼び出しでは、トリガーを使用してバックグラウンド タスクを開始します。 イベント ドリブン トリガーの使用例を次に示します。
- UI または別のジョブは、キューにメッセージを配置します。 メッセージには、ユーザーが注文を行うなど、実行されたアクションに関するデータが含まれています。 バックグラウンド タスクはこのキューを監視し、新しいメッセージが到着すると検出します。 メッセージを読み取り、その中のデータをバックグラウンド ジョブへの入力として使用します。 このパターンは、 非同期メッセージ ベースの通信と呼ばれます。
- UI または別のジョブは、ストレージ内の値を保存または更新します。 バックグラウンド タスクはストレージを監視し、変更を検出します。 データを読み取り、バックグラウンド ジョブへの入力として使用します。
- UI または別のジョブは、HTTPS URI や Web サービスとして公開されている API などのエンドポイントに対して要求を行います。 要求の一部としてバックグラウンド タスクを完了するために必要なデータが渡されます。 エンドポイントまたは Web サービスは、データを入力として使用するバックグラウンド タスクを呼び出します。
イベント ドリブンの呼び出しに適したタスクの一般的な例としては、画像処理、ワークフロー、リモート サービスへの情報の送信、電子メール メッセージの送信、マルチテナント アプリケーションでの新しいユーザーのプロビジョニングなどがあります。
スケジュール駆動型トリガー
スケジュールドリブン呼び出しでは、タイマーを使用してバックグラウンド タスクを開始します。 スケジュール ドリブン トリガーの使用例を次に示します。
- アプリケーション内またはアプリケーションのオペレーティング システムの一部としてローカルで実行されているタイマーは、バックグラウンド タスクを定期的に呼び出します。
- Azure Logic Apps などの別のアプリケーションで実行されているタイマーは、API または Web サービスに定期的に要求を送信します。 API または Web サービスがバックグラウンド タスクを呼び出します。
- 別のプロセスまたはアプリケーションは、指定した時間の遅延後、または特定の時刻にバックグラウンド タスクを 1 回呼び出すタイマーを開始します。
スケジュールドリブン呼び出しに適したタスクの一般的な例としては、バッチ処理ルーチン (最近の動作に基づいてユーザーの関連製品リストを更新するなど)、ルーチン データ処理タスク (インデックスの更新や累積結果の生成など)、日次レポートのデータ分析、データ保持のクリーンアップ、データ整合性チェックなどがあります。
1 つのインスタンスとして実行する必要があるスケジュールドリブン タスクを使用する場合は、次の点に注意してください。
- スケジューラを実行しているコンピューティング インスタンス (Windows のスケジュールされたタスクを使用する仮想マシンなど) がスケーリングされると、スケジューラの複数のインスタンスが実行されます。 これにより、タスクの複数のインスタンスが開始される可能性があります。 この詳細については、べき等に関するこのブログ記事をお読みください。
- タスクがスケジューラ イベント間の期間を超えて実行される場合、スケジューラは、前のインスタンスがまだ実行されている間に、タスクの別のインスタンスを開始する可能性があります。
結果の返送
バックグラウンド ジョブは、UI またはバックグラウンド タスクを呼び出したプロセスとは別のプロセス、または別の場所で非同期的に実行されます。 理想的には、バックグラウンド タスクは "起動と忘れ" 操作であり、その実行の進行状況は UI や呼び出し元のプロセスに影響しません。 これは、呼び出し元のプロセスがタスクの完了を待機しないことを意味します。 そのため、タスクが終了したときに自動的に検出することはできません。
バックグラウンド タスクが、進行状況または完了を示すために呼び出し元タスクと通信する必要がある場合は、このメカニズムを実装する必要があります。 いくつかの例を次に示します。
- UI または呼び出し元タスクからアクセスできる状態インジケーター値をストレージに書き込みます。この値は、必要に応じて監視またはチェックできます。 バックグラウンド タスクが呼び出し元に返す必要があるその他のデータは、同じストレージに配置できます。
- 応答キューを設定し、そこで UI または呼び出し元を待機させる。 バックグラウンド タスクは、状態と完了を示すメッセージをキューに送信できます。 バックグラウンド タスクが呼び出し元に返す必要があるデータは、メッセージに配置できます。 Azure Service Bus を使用している場合は、 ReplyTo プロパティと CorrelationId プロパティを使用してこの機能を実装できます。
- UI または呼び出し元がステータス情報を取得するためにアクセスできるバックグラウンド タスクから API またはエンドポイントを公開します。 バックグラウンド タスクが呼び出し元に返す必要があるデータを応答に含めることができます。
- バックグラウンド タスクで、API を介して UI または呼び出し元にコールバックして、定義済みのポイントまたは完了時の状態を示すようにします。 これは、ローカルで発生するイベントや、発行者-購読者モデルを通じて発生します。 バックグラウンド タスクが呼び出し元に返す必要があるデータは、要求またはイベント ペイロードに含めることができます。
ホスティング環境
さまざまな Azure プラットフォーム サービスを使用してバックグラウンド タスクをホストできます。
- Azure Web Apps と WebJobs。 Web ジョブを使用すると、Web アプリのコンテキスト内のさまざまな種類のスクリプトまたは実行可能プログラムに基づいてカスタム ジョブを実行できます。
- Azure Functions。 長時間実行されないバックグラウンド ジョブには関数を使用できます。 もう 1 つのユース ケースは、ワークロードが App Service プランで既にホストされており、使用率が低い場合です。
- Azure Virtual Machines。 Windows サービスを使用している場合、または Windows タスク スケジューラを使用する場合は、専用の仮想マシン内でバックグラウンド タスクをホストするのが一般的です。
- Azure Batch。 Batch は、仮想マシンのマネージド コレクションで実行するコンピューティング集中型の作業をスケジュールするプラットフォーム サービスです。 コンピューティング リソースを自動的にスケーリングできます。
- Azure Kubernetes Service (AKS)。 Azure Kubernetes Service は、Azure 上の Kubernetes 用のマネージド ホスティング環境を提供します。
- Azure Container Apps。 Azure Container Apps を使用すると、コンテナーに基づいてサーバーレス マイクロサービスを構築できます。
次のセクションでは、これらのオプションについて詳しく説明し、適切なオプションの選択に役立つ考慮事項を含めます。
Azure Web Apps と WebJobs
Azure WebJobs を使用して、Azure Web アプリ内でバックグラウンド タスクとしてカスタム ジョブを実行できます。 Web ジョブは、Web アプリのコンテキスト内で継続的なプロセスとして実行されます。 また、Web ジョブは、Azure Logic Apps からのトリガー イベントや、ストレージ BLOB やメッセージ キューの変更などの外部要因に応答して実行されます。 ジョブはオンデマンドで開始および停止でき、正常にシャットダウンできます。 継続的に実行されている Web ジョブが失敗すると、自動的に再起動されます。 再試行アクションとエラー アクションは構成可能です。
Web ジョブを構成する場合:
- ジョブがイベント ドリブン トリガーに応答する場合は、[ 継続的に実行] として構成する必要があります。 スクリプトまたはプログラムは、site/wwwroot/app_data/jobs/continuous という名前のフォルダーに格納されます。
- ジョブがスケジュールドリブン トリガーに応答する場合は、スケジュール に従って実行として構成する必要があります。 スクリプトまたはプログラムは、site/wwwroot/app_data/jobs/triggered という名前のフォルダーに格納されます。
- ジョブの構成時 に [オンデマンドで実行 ] オプションを選択した場合、ジョブの起動時 に [スケジュール時に実行 ] オプションと同じコードが実行されます。
Azure WebJobs は、Web アプリのサンドボックス内で実行されます。 これは、環境変数にアクセスし、接続文字列などの情報を Web アプリと共有できることを意味します。 Web ジョブは、それを実行しているコンピューターの一意の識別子にアクセスすることができます。 AzureWebJobsStorage という名前の接続文字列は、アプリケーション データの Azure Storage キュー、BLOB、テーブルへのアクセスと、メッセージングと通信のための Service Bus へのアクセスを提供します。 AzureWebJobsDashboard という名前の接続文字列は、ジョブ アクション ログ ファイルへのアクセスを提供します。
Azure WebJobs には、次の特性があります。
- セキュリティ: Web ジョブは、Web アプリのデプロイ資格情報によって保護されます。
- サポートされているファイルの種類: コマンド スクリプト (
.cmd
)、バッチ ファイル (.bat
)、PowerShell スクリプト (.ps1
)、Bash シェル スクリプト (.sh
)、PHP スクリプト (.php
)、Python スクリプト (.py
)、JavaScript コード (.js
)、実行可能プログラム (.exe
、.jar
など) を使用して、Web ジョブを定義できます。 - デプロイ: スクリプトと実行可能ファイルをデプロイするには、 Azure portal を使用するか、 Visual Studio を使用するか、 Azure WebJobs SDK を使用するか、次の場所に直接コピーします。
- トリガーされた実行の場合: site/wwwroot/app_data/jobs/triggered/{job name}
- 継続的実行の場合: site/wwwroot/app_data/jobs/continuous/{job name}
- ログ: Console.Out は INFO として扱われます (マークされています)。 Console.Error は ERROR として扱われます。 Azure portal を使用して、監視と診断の情報にアクセスできます。 ログ ファイルは、サイトから直接ダウンロードできます。 これらは次の場所に保存されます。
- トリガーされた実行の場合: Vfs/data/jobs/triggered/jobName
- 連続実行の場合: Vfs/data/jobs/continuous/jobName
- 構成: ポータル、REST API、PowerShell を使用して Web ジョブを構成できます。 ジョブ スクリプトと同じルート ディレクトリにある settings.job という名前の構成ファイルを使用して、ジョブの構成情報を提供できます。 例えば:
- { "停止待機時間": 60 }
- { "is_singleton": true }
考慮事項
- 既定では、Web ジョブは Web アプリを使用してスケーリングされます。 ただし、 is_singleton 構成プロパティを true に設定することで、単一インスタンスで実行するジョブを構成できます。 単一インスタンスの Web ジョブは、インデックスの再作成、データ分析、同様のタスクなど、同時に複数のインスタンスとしてスケーリングまたは実行したくないタスクに役立ちます。
- Web アプリのパフォーマンスに対するジョブの影響を最小限に抑えるには、実行時間の長い Web ジョブまたはリソースを集中的に使用する Web ジョブをホストするために、新しい App Service プランに空の Azure Web App インスタンスを作成することを検討してください。
Azure Functions (アジュール ファンクションズ)
Web ジョブに似たオプションは Azure Functions です。 このサービスはサーバーレスであり、短期間実行されるイベント ドリブン トリガーに最適です。 関数は、設定された時刻に実行するように構成されている場合に、タイマー トリガーを使用してスケジュールされたジョブを実行するためにも使用できます。
Azure Functions は、予期しないタイムアウトの問題を引き起こす可能性があるため、実行時間の長い大規模なタスクには推奨されません。 ただし、ホスティング プランによっては、スケジュール駆動型トリガーと見なすことができます。
考慮事項
バックグラウンド タスクがイベントに応答して短時間実行されることが予想される場合は、従量課金プランでタスクを実行することを検討してください。 実行時間は、最大時間まで構成できます。 長時間実行される関数は、より多くのコストがかかります。 また、より多くのメモリを消費する CPU 負荷の高いジョブは、コストが高くなる可能性があります。 タスクの一部としてサービスに追加のトリガーを使用する場合は、個別に課金されます。
Premium プランは、短くても継続的に実行することが予想されるタスクの数が多い場合に適しています。 このプランは、より多くのメモリと CPU を必要とするため、コストが高くなります。 利点は、仮想ネットワーク統合などの機能を使用できることです。
専用プランは、ワークロードが既にバックグラウンド ジョブで実行されている場合に最適です。 使用率の低い VM がある場合は、同じ VM で実行し、コンピューティング コストを共有できます。
詳細については、次の記事を参照してください。
Azure Virtual Machines
バックグラウンド タスクは、Azure Web Apps へのデプロイを妨げる方法で実装される場合もあれば、これらのオプションが便利ではない場合もあります。 一般的な例は、Windows サービス、サード パーティのユーティリティ、実行可能プログラムです。 もう 1 つの例として、アプリケーションをホストするプログラムとは異なる実行環境用に記述されたプログラムがあります。 たとえば、Windows または .NET アプリケーションから実行する Unix または Linux プログラムなどです。 Azure 仮想マシンのオペレーティング システムの範囲から選択し、その仮想マシンでサービスまたは実行可能ファイルを実行できます。
仮想マシンを使用するタイミングを選択するには、 Azure App Services、Cloud Services、Virtual Machines の比較を参照してください。 Virtual Machines のオプションの詳細については、「Azure の Windows 仮想マシンのサイズ」を参照してください。 Virtual Machines で使用できるオペレーティング システムと事前構築済みイメージの詳細については、「 Azure Virtual Machines Marketplace」を参照してください。
別の仮想マシンでバックグラウンド タスクを開始するには、さまざまなオプションがあります。
- タスクが公開するエンドポイントに要求を送信することで、アプリケーションから直接タスクをオンデマンドで実行できます。 これにより、タスクに必要なデータが渡されます。 このエンドポイントはタスクを呼び出します。
- スケジュールに従って実行するようにタスクを構成するには、選択したオペレーティング システムで使用可能なスケジューラまたはタイマーを使用します。 たとえば、Windows では、Windows タスク スケジューラを使用してスクリプトとタスクを実行できます。 または、仮想マシンに SQL Server がインストールされている場合は、SQL Server エージェントを使用してスクリプトとタスクを実行できます。
- Azure Logic Apps を使用してタスクを開始するには、タスクがリッスンするキューにメッセージを追加するか、タスクが公開する API に要求を送信します。
バックグラウンド タスクを開始する方法の詳細については、前のセクション トリガー を参照してください。
考慮事項
Azure 仮想マシンにバックグラウンド タスクをデプロイするかどうかを決定するときは、次の点を考慮してください。
- 別の Azure 仮想マシンでバックグラウンド タスクをホストすると、柔軟性が提供され、開始、実行、スケジュール、リソースの割り当てを正確に制御できます。 ただし、バックグラウンド タスクを実行するためだけに仮想マシンをデプロイする必要がある場合は、ランタイム コストが増加します。
- Azure portal でタスクを監視する機能はなく、失敗したタスクの自動再起動機能もありません。ただし、仮想マシンの基本的な状態を監視し、 Azure Resource Manager コマンドレットを使用して管理することはできます。 ただし、コンピューティング ノード内のプロセスとスレッドを制御する機能はありません。 通常、仮想マシンを使用するには、タスク内のインストルメンテーションと仮想マシンのオペレーティング システムからデータを収集するメカニズムを実装するための追加の作業が必要になります。 適切な解決策の 1 つは、 Azure 用 System Center 管理パックを使用することです。
- HTTP エンドポイントを介して公開される監視プローブの作成を検討してください。 これらのプローブのコードは、正常性チェックを実行し、運用情報と統計を収集したり、エラー情報を照合して管理アプリケーションに返したりすることができます。 詳細については、「 正常性エンドポイントの監視パターン」を参照してください。
詳細については、以下を参照してください。
Azure Batch
数十、数百、または数千の VM にわたって大規模で並列のハイ パフォーマンス コンピューティング (HPC) ワークロードを実行する必要がある場合は、 Azure Batch を検討してください。
Batch サービスは、VM のプロビジョニング、VM へのタスクの割り当て、タスクの実行、進行状況の監視を行います。 Batch では、ワークロードに応じて VM を自動的にスケールアウトできます。 また、バッチは、ジョブのスケジューリングも提供します。 Azure Batch では、Linux VM と Windows VM の両方がサポートされています。
考慮事項
Batch は、本質的に並列ワークロードに対して適切に機能します。 また、最後に reduce ステップを使用して並列計算を実行したり、ノード間でのメッセージの受け渡しを必要とする並列タスクに対して メッセージパッシング インターフェイス (MPI) アプリケーション を実行したりすることもできます。
Azure Batch ジョブは、ノード (VM) のプールで実行されます。 1 つの方法は、必要な場合にのみプールを割り当て、ジョブの完了後に削除することです。 ノードはアイドル状態ではありませんが、ジョブはノードが割り当てられるまで待機する必要があるため、使用率が最大化されます。 または、プールを事前に作成することもできます。 この方法では、ジョブが開始されるまでの時間を短縮できますが、ノードがアイドル状態のままになる可能性があります。 詳細については、「 プールとコンピューティング ノードの有効期間」を参照してください。
詳細については、以下を参照してください。
Azure Kubernetes Service
Azure Kubernetes Service (AKS) は、ホストされている Kubernetes 環境を管理するため、コンテナー化されたアプリケーションのデプロイと管理が簡単になります。
コンテナーは、バックグラウンド ジョブの実行に役立ちます。 次のような利点があります。
- コンテナーでは、高密度ホスティングがサポートされます。 各 VM に複数のコンテナーを配置しながら、コンテナー内のバックグラウンド タスクを分離できます。
- コンテナー オーケストレーターは、内部負荷分散、内部ネットワークの構成、およびその他の構成タスクを処理します。
- コンテナーは、必要に応じて開始および停止できます。
- Azure Container Registry を使用すると、Azure の境界内にコンテナーを登録できます。 これには、セキュリティ、プライバシー、近接性の利点が伴います。
考慮事項
- コンテナー オーケストレーターの使用方法を理解する必要があります。 DevOps チームのスキル セットによっては、これは問題になる場合とそうでない場合があります。
詳細については、以下を参照してください。
Azure コンテナ アプリ
Azure Container Apps を使用すると、コンテナーに基づいてサーバーレス マイクロサービスを構築できます。 Container Apps の特徴は次のとおりです。
- 汎用コンテナー (特に、コンテナーにデプロイされた多くのマイクロサービスにまたがるアプリケーション向け) を実行するように最適化されています。
- Kubernetes と 、Dapr、 Kubernetes Event-driven Autoscaling (KEDA)、 envoy などのオープンソース テクノロジを利用します。
- サービスの検出やトラフィックの分割などの機能を使用して、Kubernetes スタイルのアプリとマイクロサービスをサポートします。
- トラフィックに基づくスケールをサポートし、 キューなどのイベント ソースからのプル ( スケールからゼロまでなど) をサポートすることで、イベントドリブン アプリケーション アーキテクチャを有効にします。
- 実行時間の長いプロセスをサポートし、 バックグラウンド タスクを実行できます。
考慮事項
Azure Container Apps では、基になる Kubernetes API への直接アクセスは提供されません。 Kubernetes API とコントロール プレーンへのアクセスが必要な場合は、 Azure Kubernetes Service を使用する必要があります。 ただし、Kubernetes スタイルのアプリケーションを構築したいが、すべてのネイティブ Kubernetes API とクラスター管理への直接アクセスは必要ない場合は、Container Apps により、ベスト プラクティスに基づくフル マネージド エクスペリエンスが提供されます。 このような理由から、多くのチームが、Azure Container Apps を使用してコンテナー マイクロサービスの構築を開始することを選択する場合があります。
詳細については、以下を参照してください。
クイックスタートを使用して、最初のコンテナー アプリの構築を開始できます。
パーティショニング
既存のコンピューティング インスタンス内にバックグラウンド タスクを含める場合は、これがコンピューティング インスタンスとバックグラウンド タスク自体の品質属性にどのように影響するかを検討する必要があります。 これらの要因は、既存のコンピューティング インスタンスとタスクを併置するか、別のコンピューティング インスタンスに分離するかを決定するのに役立ちます。
可用性: バックグラウンド タスクは、アプリケーションの他の部分、特にユーザーの操作に直接関係する UI やその他の部分と同じレベルの可用性を持つ必要がない場合があります。 バックグラウンドタスクは、遅延や接続失敗の再試行、さらには操作をキューに入れることが可能なため、可用性に影響する他の要因に対してもより許容的である可能性があります。 ただし、キューをブロックし、アプリケーション全体に影響を与える可能性のある要求のバックアップを防ぐために十分な容量が必要です。
スケーラビリティ: バックグラウンド タスクのスケーラビリティ要件は、アプリケーションの UI や対話型部分とは異なる可能性があります。 UI のスケーリングは需要のピークを満たすために必要な場合があります。一方、未処理のバックグラウンド タスクは、コンピューティング インスタンスの数が少ないほどビジー時間が短い間に完了する可能性があります。
回復性: バックグラウンド タスクのみをホストするコンピューティング インスタンスの障害は、これらのタスクの要求をキューに入れるか、タスクが再び使用可能になるまで延期できる場合、アプリケーション全体に致命的な影響を与えない可能性があります。 コンピューティング インスタンスまたはタスクを適切な時間内に再起動できる場合、アプリケーションのユーザーは影響を受けない可能性があります。
セキュリティ: バックグラウンド タスクには、UI やアプリケーションの他の部分とは異なるセキュリティ要件または制限がある場合があります。 別のコンピューティング インスタンスを使用すると、タスクに別のセキュリティ環境を指定できます。 Gatekeeper などのパターンを使用して、セキュリティと分離を最大化するために、バックグラウンド コンピューティング インスタンスを UI から分離することもできます。
パフォーマンス: バックグラウンド タスクのコンピューティング インスタンスの種類を選択して、タスクのパフォーマンス要件に特に一致させることができます。 これは、タスクが UI と同じ処理機能を必要としない場合は低コストのコンピューティング オプションを使用し、追加の容量とリソースが必要な場合は大きなインスタンスを使用することを意味する可能性があります。
管理容易性: バックグラウンド タスクの開発とデプロイのリズムは、メイン アプリケーション コードや UI とは異なる場合があります。 それらを別のコンピューティング インスタンスにデプロイすると、更新とバージョン管理が簡略化されます。
コスト: バックグラウンド タスクを実行するためにコンピューティング インスタンスを追加すると、ホスティング コストが増加します。 追加容量とこれらの追加コストの間のトレードオフを慎重に検討する必要があります。
詳細については、「 リーダー選択パターン 」および「 競合コンシューマー」パターンを参照してください。
対立
バックグラウンド ジョブのインスタンスが複数ある場合は、データベースやストレージなどのリソースやサービスへのアクセスを競合させる可能性があります。 この同時アクセスにより、リソースの競合が発生し、サービスの可用性とストレージ内のデータの整合性の競合が発生する可能性があります。 ペシミスティック ロックアプローチを使用して、リソースの競合を解決できます。 これにより、タスクの競合するインスタンスがサービスに同時にアクセスしたり、データが破損したりするのを防ぐことができます。
競合を解決するもう 1 つの方法は、バックグラウンド タスクをシングルトンとして定義し、実行中のインスタンスが 1 つだけになるようにすることです。 ただし、これにより、複数インスタンス構成で提供できる信頼性とパフォーマンスの利点がなくなります。 これは、UI が複数のバックグラウンド タスクをビジー状態に保つために十分な作業を提供できる場合に特に当てはまります。
バックグラウンド タスクを自動的に再起動できることと、需要のピークに対処するのに十分な容量があることを確認することが重要です。 これを実現するには、十分なリソースを持つコンピューティング インスタンスを割り当てるか、需要が減少したときに後で実行するための要求を格納できるキューメカニズムを実装するか、これらの手法を組み合わせて使用します。
調整
バックグラウンド タスクは複雑であり、結果を生成したり、すべての要件を満たすために複数の個別のタスクを実行する必要がある場合があります。 これらのシナリオでは、タスクを、複数のコンシューマーが実行できる小さな目立たないステップまたはサブタスクに分割するのが一般的です。 複数のジョブで個々のステップを再利用できるため、複数ステップのジョブの効率と柔軟性が向上します。 また、手順の順序を追加、削除、または変更することも簡単です。
複数のタスクと手順の調整は困難な場合がありますが、ソリューションの実装をガイドするために使用できる一般的なパターンは 3 つあります。
タスクを複数の再利用可能なステップに分解する。 アプリケーションは、処理する情報に対してさまざまな複雑さのタスクを実行する必要がある場合があります。 このアプリケーションを実装するための簡単で柔軟性のないアプローチは、モノリシック モジュールとしてこの処理を実行することです。 ただし、この方法では、コードのリファクタリング、最適化、またはアプリケーション内の別の場所で同じ処理の一部が必要な場合に再利用する機会が減る可能性があります。 詳細については、「 パイプとフィルター」パターンを参照してください。
タスクのステップの実行の管理。 アプリケーションは、さまざまな手順を構成するタスクを実行する場合があります (その一部は、リモート サービスを呼び出したり、リモート リソースにアクセスしたりする場合があります)。 個々のステップは互いに独立している場合がありますが、タスクを実装するアプリケーション ロジックによって調整されます。 詳細については、「 Scheduler Agent Supervisor パターン」を参照してください。
失敗したタスク ステップの回復の管理。 1 つ以上のステップが失敗した場合、アプリケーションは一連のステップ (最終的に一貫性のある操作を定義する) によって実行される作業を元に戻す必要がある場合があります。 詳細については、「 補正トランザクション パターン」を参照してください。
回復性に関する考慮事項
アプリケーションに信頼性の高いサービスを提供するには、バックグラウンド タスクに回復性が必要です。 バックグラウンド タスクを計画および設計する場合は、次の点を考慮してください。
バックグラウンド タスクは、データを破損したり、アプリケーションに不整合を発生させたりすることなく、再起動を適切に処理できる必要があります。 実行時間の長いタスクまたは複数ステップのタスクの場合は、ジョブの状態を永続的ストレージに保存するか、またはキュー内のメッセージ (適切な場合) として 、チェック ポイント を使用することを検討してください。 たとえば、キュー内のメッセージに状態情報を保持し、タスクの進行状況でこの状態情報を増分更新して、最初から再開するのではなく、最後に正常なチェックポイントからタスクを処理できるようにすることができます。 Azure Service Bus キューを使用する場合は、メッセージ セッションを使用して同じシナリオを有効にすることができます。 セッションを使用すると、 SetState メソッドと GetState メソッドを使用して、アプリケーションの処理状態を保存および取得できます。 信頼性の高いマルチステップ プロセスとワークフローの設計の詳細については、 Scheduler Agent Supervisor パターンを参照してください。
キューを使用してバックグラウンド タスクと通信する場合、キューは、アプリケーションが通常よりも高い負荷を受けているときにタスクに送信されるリクエストを格納するバッファとして機能します。 これにより、タスクが比較的余裕のある時間帯にUIと同期することができます。 また、再起動しても UI がブロックされないことも意味します。 詳細については、「 Queue-Based 負荷平準化パターン」を参照してください。 一部のタスクが他のタスクよりも重要な場合は、 優先度キュー パターン を実装して、重要度の低いタスクより前にこれらのタスクを確実に実行することを検討してください。
メッセージまたはプロセス メッセージによって開始されるバックグラウンド タスクは、順序が整って届かないメッセージ、エラーが繰り返し発生するメッセージ ( 有害メッセージと呼ばれることが多い)、複数回配信されるメッセージなどの不整合を処理するように設計する必要があります。 次の点を考慮してください。
既存のデータ値に基づいてデータを変更するメッセージなど、特定の順序で処理する必要があるメッセージ (既存の値に値を追加するなど) は、送信された元の順序で到着しない可能性があります。 または、各インスタンスの負荷が異なるため、バックグラウンド タスクの異なるインスタンスによって異なる順序で処理される場合があります。 特定の順序で処理する必要があるメッセージには、シーケンス番号、キー、またはバックグラウンド タスクが正しい順序で処理されるようにするために使用できるその他のインジケーターが含まれている必要があります。 Azure Service Bus を使用している場合は、メッセージ セッションを使用して配信順序を保証できます。 ただし、メッセージの順序が重要でないようにプロセスを設計する方が、可能な場合は通常、より効率的です。
通常、バックグラウンドタスクはキュー内のメッセージをのぞき見し、これにより他のメッセージコンシューマーからそれらが一時的に非表示になります。 その後、メッセージが正常に処理された後、メッセージが削除されます。 メッセージの処理中にバックグラウンド タスクが失敗した場合、ピーク タイムアウトの有効期限が切れると、そのメッセージがキューに再び表示されます。 タスクの別のインスタンスによって、またはこのインスタンスの次の処理サイクル中に処理されます。 メッセージがコンシューマーで一貫してエラーを引き起こす場合は、タスク、キュー、およびキューがいっぱいになったときに最終的にアプリケーション自体がブロックされます。 そのため、キューから有害メッセージを検出して削除することが重要です。 Azure Service Bus を使用している場合、エラーの原因となるメッセージは、自動的または手動で関連付けられている 配信不能キューに移動できます。
キューは 、少なくとも 1 回 の配信メカニズムで保証されますが、同じメッセージを複数回配信する場合があります。 さらに、メッセージを処理した後、キューから削除する前にバックグラウンド タスクが失敗した場合、メッセージは再び処理できるようになります。 バックグラウンド タスクはべき等性を持つ必要があります。つまり、同じメッセージを複数回処理しても、アプリケーションのデータにエラーや不整合が発生しないことを意味します。 格納された値を特定の新しい値に設定するなど、一部の操作は自然に冪等です。 ただし、保存された値がメッセージが最初に送信されたときと同じであることを確認せずに既存の格納された値に値を追加するなどの操作は、不整合を引き起こします。 Azure Service Bus キューは、重複したメッセージを自動的に削除するように構成できます。 少なくとも一度のメッセージ配信における問題について詳しく知りたい方は、冪等性を伴うメッセージ処理に関するガイダンスをご覧ください。
Azure Queue Storage や Azure Service Bus キューなどの一部のメッセージング システムでは、キューからメッセージが読み取られた回数を示すキューのカウント解除プロパティがサポートされています。 これは、繰り返しメッセージと有害メッセージを処理する場合に役立ちます。 詳細については、「 非同期メッセージング入門 と べき等パターン」を参照してください。
スケーリングおよびパフォーマンスに関する考慮事項
バックグラウンド タスクでは、アプリケーションがブロックされないように十分なパフォーマンスを提供する必要があります。また、システムの負荷が高い場合に、操作の遅延が原因で不整合が発生する可能性があります。 通常、バックグラウンド タスクをホストするコンピューティング インスタンスをスケーリングすることで、パフォーマンスが向上します。 バックグラウンド タスクを計画および設計する場合は、スケーラビリティとパフォーマンスに関する次の点を考慮してください。
Azure では、現在の需要と負荷、または定義済みのスケジュールに基づいて、Web Apps と Virtual Machines でホストされているデプロイの自動スケール (スケールアウトとスケールバックの両方) がサポートされています。 この機能を使用して、実行時のコストを最小限に抑えながら、アプリケーション全体に十分なパフォーマンス機能があることを確認します。
バックグラウンド タスクのパフォーマンス機能がアプリケーションの他の部分 (UI やデータ アクセス 層などのコンポーネントなど) とは異なる場合、バックグラウンド タスクを個別のコンピューティング サービスでまとめてホストすることで、UI タスクとバックグラウンド タスクを個別にスケーリングして負荷を管理できます。 複数のバックグラウンド タスクのパフォーマンス機能が互いに大きく異なる場合は、それらを分割し、各種類を個別にスケーリングすることを検討してください。 ただし、これにより実行時コストが増加する可能性があることに注意してください。
コンピューティング リソースをスケーリングするだけでは、負荷がかかっているパフォーマンスの損失を防ぐには不十分な場合があります。 また、処理チェーン全体の 1 つのポイントがボトルネックにならないように、ストレージ キューやその他のリソースをスケーリングする必要がある場合もあります。 また、ストレージの最大スループットや、アプリケーションやバックグラウンド タスクが依存するその他のサービスなど、他の制限事項も考慮してください。
バックグラウンド タスクはスケーリング用に設計する必要があります。 たとえば、適切なキューでメッセージをリッスンまたは送信するために、使用中のストレージ キューの数を動的に検出できる必要があります。
既定では、Web ジョブは、関連付けられている Azure Web Apps インスタンスに合わせてスケーリングされます。 ただし、Web ジョブを 1 つのインスタンスとしてのみ実行する場合は、JSON データ { "is_singleton": true }を含む Settings.job ファイルを作成できます。 これにより、関連付けられている Web アプリのインスタンスが複数存在する場合でも、Azure では Web ジョブのインスタンスが 1 つだけ実行されます。 これは、1 つのインスタンスとして実行する必要があるスケジュールされたジョブに便利な手法です。