Durable Functions 中的计时器 (Azure Functions)Timers in Durable Functions (Azure Functions)

Durable Functions 提供了供在业务流程协调程序函数中使用的“持久计时器”,这些计时器用来为异步操作实现延迟或设置超时。 Durable Functions provides durable timers for use in orchestrator functions to implement delays or to set up timeouts on async actions. 在业务流程协调程序函数中应当使用持久计时器,而不是使用 Thread.SleepTask.Delay (C#) 或 setTimeout()setInterval() (JavaScript)。Durable timers should be used in orchestrator functions instead of Thread.Sleep and Task.Delay (C#), or setTimeout() and setInterval() (JavaScript).

创建持久计时器的方法是:调用业务流程触发器绑定CreateTimer (.NET) 方法或 createTimer (JavaScript) 方法。You create a durable timer by calling the CreateTimer (.NET) method or the createTimer (JavaScript) method of the orchestration trigger binding. 该方法返回一个将在指定的日期和时间完成的任务。The method returns a task that completes on a specified date and time.

计时器限制Timer limitations

创建在下午 4:30 过期的计时器时,基础 Durable Task Framework 会将一条仅在下午 4:30 才变得可见的消息排入队列。When you create a timer that expires at 4:30 pm, the underlying Durable Task Framework enqueues a message that becomes visible only at 4:30 pm. 当在 Azure Functions 消耗计划中运行时,新近可见的计时器消息将确保在合适的 VM 上激活函数应用。When running in the Azure Functions Consumption plan, the newly visible timer message will ensure that the function app gets activated on an appropriate VM.

备注

  • 持久计时器目前的限制为 7 天。Durable timers are currently limited to 7 days. 如果需要更长的延迟,可以在 while 循环中使用计时器 API 对其进行模拟。If longer delays are needed, they can be simulated using the timer APIs in a while loop.
  • 计算持久计时器的触发时间时,请始终在 .NET 中使用 CurrentUtcDateTime 而非 DateTime.UtcNow,在 JavaScript 中使用 currentUtcDateTime 而非 Date.nowDate.UTCAlways use CurrentUtcDateTime instead of DateTime.UtcNow in .NET or currentUtcDateTime instead of Date.now or Date.UTC in JavaScript when computing the fire time for durable timers. 有关详细信息,请参阅业务流程协调程序函数代码约束一文。For more information, see the orchestrator function code constraints article.

延迟的用法Usage for delay

下面的示例演示了如何使用持久计时器来延迟执行。The following example illustrates how to use durable timers for delaying execution. 示例连续 10 天每天都会发出账单通知。The example is issuing a billing notification every day for 10 days.

[FunctionName("BillingIssuer")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    for (int i = 0; i < 10; i++)
    {
        DateTime deadline = context.CurrentUtcDateTime.Add(TimeSpan.FromDays(1));
        await context.CreateTimer(deadline, CancellationToken.None);
        await context.CallActivityAsync("SendBillingEvent");
    }
}

备注

前面的 C# 示例以 Durable Functions 2.x 为目标。The previous C# example targets 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.

警告

请避免在业务流程协调程序函数中出现无限循环。Avoid infinite loops in orchestrator functions. 有关如何安全有效地实现无限循环方案的信息,请参阅永久业务流程For information about how to safely and efficiently implement infinite loop scenarios, see Eternal Orchestrations.

超时的用法Usage for timeout

此示例演示了如何使用持久计时器来实现超时。This example illustrates how to use durable timers to implement timeouts.

[FunctionName("TryGetQuote")]
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("GetQuote");
        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# example targets 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.

警告

使用 CancellationTokenSource (.NET) 或对返回的 TimerTask (JavaScript) 调用 cancel() 来取消持久计时器(如果代码不会等待它完成)。Use a CancellationTokenSource (.NET) or call cancel() on the returned TimerTask (JavaScript) to cancel a durable timer if your code will not wait for it to complete. 在所有未完成任务都完成或取消之前,Durable Task Framework 不会将业务流程的状态更改为“已完成”。The Durable Task Framework will not change an orchestration's status to "completed" until all outstanding tasks are completed or canceled.

此取消机制不会终止正在进行的活动函数执行或子业务流程执行。This cancellation mechanism doesn't terminate in-progress activity function or sub-orchestration executions. 它只是允许业务流程协调程序函数忽略结果并继续运行。Rather, it simply allows the orchestrator function to ignore the result and move on. 如果函数应用使用了消耗计划,则还需要为已放弃的活动函数消耗的任何时间和内存付费。If your function app uses the Consumption plan, you'll still be billed for any time and memory consumed by the abandoned activity function. 默认情况下,在消耗计划中运行的函数有五分钟的超时。By default, functions running in the Consumption plan have a timeout of five minutes. 如果超出了此限制,则会回收 Azure Functions 主机以停止所有执行并防止出现费用失控的情况。If this limit is exceeded, the Azure Functions host is recycled to stop all execution and prevent a runaway billing situation. 函数超时是可配置的The function timeout is configurable.

后续步骤Next steps