对于后台作业,通常需要确保一次仅运行一个特定的编排器实例,以防止重复的编排同时运行。 可以在 Durable Functions 或 Durable Task SDKs 中实现单一实例模式,方法是在创建时将特定的实例 ID 分配给业务流程协调程序,然后检查具有该 ID 的实例是否已经在运行,再启动新的实例。
本文展示如何通过每种支持语言的代码示例实现单例协调器。
先决条件
- 熟悉 Durable Task 业务流程 和 任务中心
- 现有 Durable Functions 或 Durable Task SDK 项目
注意
单一实例模式中存在潜在的竞态条件。 如果两个客户端同时执行检查和启动逻辑,则两个调用可能会报告成功,但实际上只有一个业务流程实例启动。 根据你的要求,这可能会产生不良的副作用。 如果需要严格的单实例保证,请考虑添加其他锁定机制。
重要
目前,PowerShell Durable Task SDK 不可用。
单例协调器示例
重要
对进程内模型的支持将于 2026 年 11 月 10 日结束。 为获得完全支持,强烈建议将应用迁移到独立工作模型。
以下示例演示了一个 HTTP 触发器函数,该函数创建单例后台作业协调。 代码尝试确保指定实例 ID 仅存在一个活动实例。
这段 C# 代码使用独立工作进程模型,这是 .NET 应用的推荐模型。 有关进程内和独立工作者模型之间差异的更多信息,请参阅 Durable Functions 版本一文。
[Function("HttpStartSingle")]
public static async Task<HttpResponseData> RunSingle(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "orchestrators/{functionName}/{instanceId}")] HttpRequestData req,
[DurableClient] DurableTaskClient starter,
string functionName,
string instanceId,
FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger("HttpStartSingle");
// Check if an instance with the specified ID already exists or an existing one stopped running(completed/failed/terminated).
OrchestrationMetadata? existingInstance = await starter.GetInstanceAsync(instanceId, getInputsAndOutputs: false);
if (existingInstance == null
|| existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Completed
|| existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Failed
|| existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Terminated)
{
// An instance with the specified ID doesn't exist or an existing one stopped running, create one.
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
await starter.ScheduleNewOrchestrationInstanceAsync(functionName, requestBody, new StartOrchestrationOptions { InstanceId = instanceId });
logger.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return await starter.CreateCheckStatusResponseAsync(req, instanceId);
}
else
{
// An instance with the specified ID exists or an existing one still running, don't create one.
var response = req.CreateResponse(HttpStatusCode.Conflict);
await response.WriteStringAsync($"An instance with ID '{instanceId}' already exists.");
return response;
}
}
以下示例演示如何使用 Durable Task SDKs 创建单例协调。 代码尝试确保指定实例 ID 仅存在一个活动实例。
using Microsoft.DurableTask.Client;
// Check if an instance with the specified ID already exists
string instanceId = "singleton-job";
OrchestrationMetadata? existingInstance = await client.GetInstanceAsync(instanceId, getInputsAndOutputs: false);
if (existingInstance == null ||
existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Completed ||
existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Failed ||
existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Terminated)
{
// An instance with the specified ID doesn't exist or an existing one stopped running, create one.
await client.ScheduleNewOrchestrationInstanceAsync("MyOrchestration", input, new StartOrchestrationOptions(instanceId));
Console.WriteLine($"Started orchestration with ID = '{instanceId}'.");
}
else
{
// An instance with the specified ID exists or an existing one still running.
Console.WriteLine($"An instance with ID '{instanceId}' already exists.");
}
单例模式的工作原理
由于实例 ID 在任务中心内是唯一的,因此计划具有已知、固定 ID 的业务流程,并首先检查其状态会阻止重复的并发运行。 默认情况下,实例 ID 是随机生成的 GUID。 但是,在前面的示例中,将传入特定的实例 ID。 然后,该代码提取业务流程实例元数据,以检查具有该 ID 的实例是否已运行。 如果未运行此类实例,则会使用该 ID 创建新实例。
协调器函数本身可以使用任何模式:启动和完成的标准函数,或持续运行的 永久协调。 单一实例模式仅控制并发运行的实例数。