Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
永恒编排 是协调器函数,通过使用 continue-as-new API 定期重置自身历史记录而持续运行。 它们对于聚合器、定期后台作业和任何需要无限循环且没有无限历史记录增长的Durable Functions方案非常有用。
没有 continue-as-new 时,一个无限循环的协调器在每次调度任务时都会累积 业务流程历史记录,最终导致性能问题和内存消耗过度。 永恒的业务流程模式通过重置每次迭代的历史记录来解决此问题。
注意
永恒编排代码样例提供适用于 C#、JavaScript、Python 和 Java。 PowerShell 不支持 continue-as-new。
本文内容:
- “继续作为新”机制如何运作 — 重置机制
- 注意事项 - 异常行为、不完整的任务和外部事件
- 定期工作实例 - 旨在避免计时器重叠的清理循环
- 启动永久编排 - 实施和单例模式
- 退出永恒的业务流程 - 正常停止和终止
永久操作编排 是通过使用 API 定期重置自己的历史记录来无限期运行的工作流。 它们对于聚合器、周期性后台任务以及任何需要无限循环但不会导致历史记录无限增长的场景都非常有用。
如果没有 continue-as-new,永久循环的编排在每个计划任务中都会累计历史记录,最终导致性能问题和过多的内存使用。 永恒的业务流程模式通过重置每次迭代的历史记录来解决此问题。
重要
目前,PowerShell Durable Task SDK 不可用。
本文内容:
- “继续作为新”机制如何运作 — 重置机制
- 注意事项 - 异常行为、不完整的任务和外部事件
- 定期工作实例 - 旨在避免计时器重叠的清理循环
- 启动永久编排 - 实施和单例模式
- 退出永恒的业务流程 - 正常停止和终止
如何继续作为新工作
协调器函数通过调用continue-as-new协调触发器绑定的方法来重置其状态,而不是使用无限循环。 此方法采用 JSON 可序列化参数,该参数将成为下一个业务流程协调程序函数生成的新输入。
调用 continue-as-new时,业务流程实例会用新的输入值重启自身。 保留相同的实例 ID,但调度器函数的历史记录会重置。
编排通过在编排上下文上调用 continue-as-new 方法来重置其状态,而不是使用无限循环。 此方法采用 JSON 可序列化参数,该参数将成为下一代业务流程的新输入。
调用 continue-as-new时,业务流程实例会用新的输入值重启自身。 保留相同的实例 ID,但编排的历史记录会重置。
持续编排注意事项
在编排流程中使用 continue-as-new 方法时,请记住以下注意事项:
通过使用
continue-as-new方法重置业务流程协调程序函数时,Durable Task Framework 将维持相同的实例 ID,但会在内部创建并使用新的 执行 ID。 此执行 ID 不会在外部公开,但在调试业务流程执行时非常有用。在执行期间发生未经处理的异常时,业务流程将进入 失败 状态并终止执行。 对块的调用
continue-as-newfinally在未捕获的异常后重启业务流程。当业务流程调用
continue-as-new时,任何未完成任务的结果都会被丢弃。 例如,如果一个计时器被设置并且在计时器触发之前调用continue-as-new,则计时器事件将被丢弃。可以选择在
continue-as-new重启时保留未处理的外部事件。 在 C# 中,ContinueAsNew默认保留未处理的事件。 在 Java 中,continueAsNew默认也会保留事件。 在 Python 中,除非continue_as_new,否则save_events=True不会保留事件。 在 JavaScript 中,continueAsNew需要参数saveEvents(true或false)来控制此行为。
在编排流程中使用 continue-as-new 方法时,请记住以下注意事项:
通过使用
continue-as-new方法重置业务流程时,该 Durable Task SDK 会维护相同的实例 ID,但在内部会创建并使用一个新的 执行 ID。 此执行 ID 不会在外部公开,但在调试业务流程执行时可能很有用。在执行期间发生未经处理的异常时,业务流程将进入 失败 状态并终止执行。 对块的调用
continue-as-newfinally在未捕获的异常后重启业务流程。当业务流程调用
continue-as-new时,任何未完成任务的结果都会被丢弃。 例如,如果一个计时器被设置并且在计时器触发之前调用continue-as-new,则计时器事件将被丢弃。可以选择在
continue-as-new重启时保留未处理的外部事件。 在.NET和Java中,continue-as-new默认保留未处理的事件。 在 Python 中,除非continue_as_new,否则save_events=True不会保留事件。 在 JavaScript 中,continueAsNew需要参数saveEvents(true或false)来控制此行为。 在所有情况下,当业务流程下次调用waitForExternalEvent或者wait_for_external_event时,都会传递未处理事件。
定期工作示例
持久业务编排的一个常见用例是周期性后台工作,例如清理任务。
为什么不使用计时器触发器? 基于 CRON 的计时器触发器在固定时间运行,无论上一次运行是否已完成。 永恒的业务流程在计划下一次迭代之前等待工作完成,因此运行永远不会重叠。
| Approach | 计划(1 小时间隔,30 分钟作业) | 重叠风险 |
|---|---|---|
| 计时器触发器 (CRON) | 1:00, 2:00, 3:00 | 是 — 如果作业超出间隔 |
| 永恒编排 | 1:00, 2:30, 4:00 | 否 — 下一次运行等待完成 |
[FunctionName("Periodic_Cleanup_Loop")]
public static async Task Run(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
await context.CallActivityAsync("DoCleanup", null);
// sleep for one hour between cleanups
DateTime nextCleanup = context.CurrentUtcDateTime.AddHours(1);
await context.CreateTimer(nextCleanup, CancellationToken.None);
context.ContinueAsNew(null);
}
public class PeriodicCleanupLoop : TaskOrchestrator<object?, object?>
{
public override async Task<object?> RunAsync(TaskOrchestrationContext context, object? input)
{
await context.CallActivityAsync("DoCleanup");
// sleep for one hour between cleanups
await context.CreateTimer(TimeSpan.FromHours(1), CancellationToken.None);
context.ContinueAsNew(null);
return null;
}
}
启动永久编排流程
使用 start-new 或 schedule-new durable client 方法启动一个无限期编排,就像任何其他编排函数一样。 若要确保一次只运行一个实例,请使用固定实例 ID。 有关更多信息,请参阅单例编排。
[FunctionName("Trigger_Eternal_Orchestration")]
public static async Task<HttpResponseMessage> OrchestrationTrigger(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage request,
[DurableClient] IDurableOrchestrationClient client)
{
string instanceId = "StaticId";
await client.StartNewAsync("Periodic_Cleanup_Loop", instanceId);
return client.CreateCheckStatusResponse(request, instanceId);
}
使用 schedule-new 客户端方法启动永续编排,就像任何其他编排一样。 若要确保一次只运行一个实例,请使用固定实例 ID。 有关更多信息,请参阅单例编排。
string instanceId = "StaticId";
await client.ScheduleNewOrchestrationInstanceAsync(
"PeriodicCleanupLoop",
null,
new StartOrchestrationOptions { InstanceId = instanceId });
退出永恒编排
如果编排器函数需要最终完成,请不要调用 continue-as-new 并使函数退出。
如果业务流程协调程序函数处于无限循环中并且需要停止,请使用业务流程客户端绑定的终止 API 来停止它。
await client.TerminateAsync(instanceId, "Cleanup no longer needed");
有关详细信息,请参阅 实例管理。
如果业务流程需要最终完成,请不要调用 continue-as-new 业务流程并让业务流程退出。
如果业务流程处于无限循环中并且需要停止,请使用持久任务客户端上的 终止 API 来停止它。
await client.TerminateInstanceAsync(instanceId, "Cleanup no longer needed");