处理 Durable Functions 中的错误 (Azure Functions)Handling errors in Durable Functions (Azure Functions)

Durable Function 业务流程采用代码实现,并可使用编程语言的内置错误处理功能。Durable Function orchestrations are implemented in code and can use the programming language's built-in error-handling features. 实际上,不需要学习任何新概念,就可以将错误处理和补偿添加到业务流程中。There really aren't any new concepts you need to learn to add error handling and compensation into your orchestrations. 但应注意以下事项。However, there are a few behaviors that you should be aware of.

活动函数中的错误Errors in activity functions

活动函数中引发的任何异常都将封送回业务流程协调程序函数,并作为 FunctionFailedException 引发。Any exception that is thrown in an activity function is marshaled back to the orchestrator function and thrown as a FunctionFailedException. 可在业务流程协调程序函数中编写满足需要的错误处理和补偿代码。You can write error handling and compensation code that suits your needs in the orchestrator function.

例如,考虑使用以下业务流程协调程序函数,将一个帐户中的资金转到另一帐户:For example, consider the following orchestrator function that transfers funds from one account to another:

[FunctionName("TransferFunds")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var transferDetails = context.GetInput<TransferOperation>();

    await context.CallActivityAsync("DebitAccount",
        new
        {
            Account = transferDetails.SourceAccount,
            Amount = transferDetails.Amount
        });

    try
    {
        await context.CallActivityAsync("CreditAccount",
            new
            {
                Account = transferDetails.DestinationAccount,
                Amount = transferDetails.Amount
            });
    }
    catch (Exception)
    {
        // Refund the source account.
        // Another try/catch could be used here based on the needs of the application.
        await context.CallActivityAsync("CreditAccount",
            new
            {
                Account = transferDetails.SourceAccount,
                Amount = transferDetails.Amount
            });
    }
}

备注

前面的 C# 示例适用于 Durable Functions 2.x。The previous C# examples are for Durable Functions 2.x. 对于 Durable Functions 1.x,必须使用 DurableOrchestrationContext 而不是 IDurableOrchestrationContextFor Durable Functions 1.x, you must use DurableOrchestrationContext instead of IDurableOrchestrationContext. 有关版本之间差异的详细信息,请参阅 Durable Functions 版本一文。For more information about the differences between versions, see the Durable Functions versions article.

如果第一个 CreditAccount 函数调用失败,业务流程协调程序函数将通过将资金贷记回源帐户进行补偿。If the first CreditAccount function call fails, the orchestrator function compensates by crediting the funds back to the source account.

失败时自动重试Automatic retry on failure

调用活动函数或子业务流程函数时,可指定自动重试策略。When you call activity functions or sub-orchestration functions, you can specify an automatic retry policy. 以下示例尝试调用某函数多达三次,每次重试之间等待 5 秒:The following example attempts to call a function up to three times and waits 5 seconds between each retry:

[FunctionName("TimerOrchestratorWithRetry")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var retryOptions = new RetryOptions(
        firstRetryInterval: TimeSpan.FromSeconds(5),
        maxNumberOfAttempts: 3);

    await context.CallActivityWithRetryAsync("FlakyFunction", retryOptions, null);

    // ...
}

备注

前面的 C# 示例适用于 Durable Functions 2.x。The previous C# examples are for Durable Functions 2.x. 对于 Durable Functions 1.x,必须使用 DurableOrchestrationContext 而不是 IDurableOrchestrationContextFor Durable Functions 1.x, you must use DurableOrchestrationContext instead of IDurableOrchestrationContext. 有关版本之间差异的详细信息,请参阅 Durable Functions 版本一文。For more information about the differences between versions, see the Durable Functions versions article.

上一示例中的活动函数调用使用一个参数来配置自动重试策略。The activity function call in the previous example takes a parameter for configuring an automatic retry policy. 可通过多种选项自定义自动重试策略:There are several options for customizing the automatic retry policy:

  • 最大尝试次数:最大重试尝试次数。Max number of attempts: The maximum number of retry attempts.
  • 首次重试间隔:首次尝试重试前需要等待的时间。First retry interval: The amount of time to wait before the first retry attempt.
  • 回退系数:用来确定回退增加速率的系数。Backoff coefficient: The coefficient used to determine rate of increase of backoff. 默认值为 1。Defaults to 1.
  • 最大重试间隔:尝试重试之间需要等待的最长时间。Max retry interval: The maximum amount of time to wait in between retry attempts.
  • 重试超时:执行重试所花费的最长时间。Retry timeout: The maximum amount of time to spend doing retries. 默认行为是可无限期重试。The default behavior is to retry indefinitely.
  • 处理:可以指定用户定义的回叫来确定是否应该重试函数。Handle: A user-defined callback can be specified to determine whether a function should be retried.

函数超时Function timeouts

如果业务流程协调程序函数内的函数调用耗时太长才能完成,建议放弃该函数调用。You might want to abandon a function call within an orchestrator function if it's taking too long to complete. 本示例中执行此操作的正确方法是将 context.CreateTimer (.NET) 或 context.df.createTimer (JavaScript) 与 Task.WhenAny (.NET) 或 context.df.Task.any (JavaScript) 结合使用,创建持久计时器,如下例中所示:The proper way to do this today is by creating a durable timer using context.CreateTimer (.NET) or context.df.createTimer (JavaScript) in conjunction with Task.WhenAny (.NET) or context.df.Task.any (JavaScript), as in the following example:

[FunctionName("TimerOrchestrator")]
public static async Task<bool> Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    TimeSpan timeout = TimeSpan.FromSeconds(30);
    DateTime deadline = context.CurrentUtcDateTime.Add(timeout);

    using (var cts = new CancellationTokenSource())
    {
        Task activityTask = context.CallActivityAsync("FlakyFunction");
        Task timeoutTask = context.CreateTimer(deadline, cts.Token);

        Task winner = await Task.WhenAny(activityTask, timeoutTask);
        if (winner == activityTask)
        {
            // success case
            cts.Cancel();
            return true;
        }
        else
        {
            // timeout case
            return false;
        }
    }
}

备注

前面的 C# 示例适用于 Durable Functions 2.x。The previous C# examples are for Durable Functions 2.x. 对于 Durable Functions 1.x,必须使用 DurableOrchestrationContext 而不是 IDurableOrchestrationContextFor Durable Functions 1.x, you must use DurableOrchestrationContext instead of IDurableOrchestrationContext. 有关版本之间差异的详细信息,请参阅 Durable Functions 版本一文。For more information about the differences between versions, see the Durable Functions versions article.

备注

此机制实际上不会终止正在进行的活动函数执行。This mechanism does not actually terminate in-progress activity function execution. 它只是允许业务流程协调程序函数忽略结果并继续运行。Rather, it simply allows the orchestrator function to ignore the result and move on. 有关详细信息,请参阅计时器文档。For more information, see the Timers documentation.

未经处理的异常Unhandled exceptions

如果业务流程协调程序函数失败,出现未经处理的异常,则会记录异常的详细信息,且实例的完成状态为 FailedIf an orchestrator function fails with an unhandled exception, the details of the exception are logged and the instance completes with a Failed status.

后续步骤Next steps