Azure Functions のエラー処理と再試行

Azure Functions でのエラーの処理は、データの損失やイベントの漏れを防ぎ、アプリケーションの正常性を監視するために重要です。 また、イベント ベースのトリガーの再試行動作を理解するための重要な方法でもあります。

この記事では、エラー処理の一般的な戦略と、使用可能な再試行方法について説明します。

重要

Timer、Kafka、Event Hubs 以外のトリガーのランタイムでの再試行ポリシーのサポートは、この機能が一般提供 (GA) された後に削除されます。 Timer と Event Hubs 以外のすべてのトリガーのプレビュー再試行ポリシーのサポートは、2022 年 12 月に削除されます。 詳しくは、「再試行」セクションをご覧ください。

エラーの処理

Azure 関数で発生するエラーは、次のいずれかによるものである可能性があります。

  • Azure Functions の組み込みのトリガーとバインドの使用
  • 基になっている Azure サービスの API の呼び出し
  • REST エンドポイントの呼び出し
  • クライアント ライブラリ、パッケージ、またはサードパーティ API の呼び出し

データやメッセージが失われないようにするには、適切なエラー処理を行うことが重要です。 このセクションでは、推奨されるエラー処理方法について説明し、詳細情報へのリンクを示します。

Application Insights を有効にする

Azure Functions は、Application Insights と統合して、エラー データ、パフォーマンス データ、ランタイム ログを収集します。 Application Insights を使用して、関数の実行で発生するエラーを検出し、よりよく理解する必要があります。 詳細については、「Azure Functions を監視する」を参照してください。

構造化エラー処理を使用する

アプリケーションの正常性を監視するには、エラーをキャプチャしてログすることが重要です。 関数コードの最上位レベルに、try/catch ブロックを含める必要があります。 catch ブロックでは、エラーをキャプチャしてログできます。 バインドによって発生する可能性があるエラーの詳細については、バインド エラー コードに関する記事を参照してください。

再試行戦略を計画する

いくつかの関数バインド拡張機能では、再試行のサポートが組み込まれています。 さらに、ランタイムでは、Timer、Kafka、Event Hubs によってトリガーされる関数の再試行ポリシーを定義できます。 詳細については、「再試行」を参照してください。 再試行動作を提供しないトリガーの場合は、独自の再試行スキームの実装が必要になる場合があります。

べき等に設計する

データの処理時にエラーが発生すると、関数にとって問題になる可能性があります (特にメッセージを処理しているとき)。 エラーが発生したときに起きることと、重複する処理を回避する方法を検討することが重要です。 詳細については、「同一入力のための Azure Functions の設計」を参照してください。

再試行

関数では、2 種類の再試行を使用できます。

  • 個々のトリガー拡張機能の組み込みの再試行動作
  • Functions ランタイムによって提供される再試行ポリシー

次の表は、再試行をサポートするトリガーと、再試行動作が構成されている場所を示しています。 また、基になるサービスからのエラーに関する詳細情報にもリンクされています。

トリガー/バインド 再試行ソース 構成
Azure Cosmos DB 再試行ポリシー 関数レベル
Azure Blob Storage バインド拡張機能 host.json
Azure Event Grid バインド拡張機能 イベント サブスクリプション
Azure Event Hubs 再試行ポリシー 関数レベル
Azure Queue Storage バインド拡張機能 host.json
RabbitMQ バインド拡張機能 配信不能キュー
Azure Service Bus バインド拡張機能 配信不能キュー
Timer 再試行ポリシー 関数レベル
Kafka 再試行ポリシー 関数レベル

再試行ポリシー

Azure Functions ランタイムのバージョン 3.x 以降では、Functions ランタイムによって適用される Timer、Kafka、Event Hubs、Azure Cosmos DB トリガーの再試行ポリシーを定義できます。

再試行ポリシーは、正常に完了するか、または再試行の最大数に達するまで、失敗した実行を再実行するようにランタイムに指示します。

Timer、Kafka、Event Hubs、または Azure Cosmos DB によってトリガーされた関数からキャッチされない例外が発生すると、再試行ポリシーが評価されます。 ベスト プラクティスとして、コード内のすべての例外をキャッチし、再試行させるエラーを再スローする必要があります。

重要

実行の再試行ポリシーが完了するまで、Event Hubs チェックポイントは書き込まれません。 この動作により、特定のパーティションの進行は、現在のバッチが完了するまで一時停止されます。

Event Hubs v5 拡張機能では、Functions ホストと Event Hubs の間の対話のための追加の再試行機能がサポートされます。 詳細については、host.json ファイルの Event Hubs セクションclientRetryOptions を参照してください。

再試行戦略

ポリシーでサポートされている 2 つの再試行戦略を構成できます。

各再試行の間に指定された時間を経過させることができます。

最大再試行回数

関数の実行が最終的に失敗するまでに再試行される最大回数を構成できます。 現在の再試行回数は、インスタンスのメモリに格納されます。

再試行と再試行の間に、インスタンスでエラーが発生する可能性があります。 再試行ポリシーの実行中にインスタンスでエラーが発生した場合、再試行回数は失われます。 インスタンスでエラーが発生すると、Event Hubs トリガーは処理を再開し、新しいインスタンスでバッチを再試行できます。再試行回数はゼロにリセットされます。 Timer トリガーは、新しいインスタンスで再開されません。

この動作は、最大再試行回数がベスト エフォートであることを意味します。 まれに、要求されている最大回数より多く、実行が再試行されることがあります。 Timer トリガーの場合、再試行が要求されている最大回数より少ないことがあります。

再試行の例

関数レベルの再試行は、次の NuGet パッケージでサポートされています。

[Function(nameof(TimerFunction))]
[FixedDelayRetry(5, "00:00:10")]
public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo timerInfo,
    FunctionContext context)
{
    var logger = context.GetLogger(nameof(TimerFunction));
    logger.LogInformation($"Function Ran. Next timer schedule = {timerInfo.ScheduleStatus.Next}");
}
プロパティ 説明
MaxRetryCount 必須。 関数の実行ごとに許可される再試行の最大回数。 -1 は、無制限に再試行することを意味します。
DelayInterval 再試行と再試行の間に使用される遅延。 HH:mm:ss という形式の文字列として指定します。

function.json ファイルの再試行ポリシーを次に示します。

{
    "disabled": false,
    "bindings": [
        {
            ....
        }
    ],
    "retry": {
        "strategy": "fixedDelay",
        "maxRetryCount": 4,
        "delayInterval": "00:00:10"
    }
}
function.json のプロパティ 説明
strategy 必須。 使用する再試行戦略。 有効な値は fixedDelay または exponentialBackoffです。
maxRetryCount 必須。 関数の実行ごとに許可される再試行の最大回数。 -1 は、無制限に再試行することを意味します。
delayInterval fixedDelay 戦略を使用するときに、再試行と再試行の間に使用される遅延。 HH:mm:ss という形式の文字列として指定します。
minimumInterval exponentialBackoff 戦略を使用していいるときの最小再試行遅延。 HH:mm:ss という形式の文字列として指定します。
maximumInterval exponentialBackoff 戦略を使用していいるときの最大再試行遅延。 HH:mm:ss という形式の文字列として指定します。

関数で再試行コンテキストを使用する Python のサンプルを次に示します。

import azure.functions
import logging


def main(mytimer: azure.functions.TimerRequest, context: azure.functions.Context) -> None:
    logging.info(f'Current retry count: {context.retry_context.retry_count}')

    if context.retry_context.retry_count == context.retry_context.max_retry_count:
        logging.warn(
            f"Max retries of {context.retry_context.max_retry_count} for "
            f"function {context.function_name} has been reached")

@FunctionName("TimerTriggerJava1")
@FixedDelayRetry(maxRetryCount = 4, delayInterval = "00:00:10")
public void run(
    @TimerTrigger(name = "timerInfo", schedule = "0 */5 * * * *") String timerInfo,
    final ExecutionContext context
) {
    context.getLogger().info("Java Timer trigger function executed at: " + LocalDateTime.now());
}

エラー コードのバインド

Azure サービスと統合しているとき、基になるサービスの API からエラーが発生する場合があります。 バインド固有のエラーに関する情報については、以下の記事の例外とリターン コードに関するセクションをご覧ください。

次のステップ