你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

持久任务中的单例业务流程协调程序

对于后台作业,你通常需要确保特定业务流程协调程序同一时间只运行一个实例,以防止重复的协调并发运行。 可以在 Durable FunctionsDurable Task SDKs 中实现单一实例模式,方法是在创建时将特定的实例 ID 分配给业务流程协调程序,然后检查具有该 ID 的实例是否已经在运行,再启动新的实例。

本文展示如何通过每种支持语言的代码示例实现单例协调器。

先决条件

注释

单例模式存在潜在的竞态条件。 如果两个客户端同时执行检查和启动逻辑,则两个调用可能会报告成功,但实际上只有一个业务流程实例启动。 根据你的要求,这可能会产生不良的副作用。 如果需要严格的单实例保证,请考虑添加其他锁定机制。

重要

目前,PowerShell Durable Task SDK 不可用。

单例业务流程协调程序示例

以下示例演示了一个 HTTP 触发器函数,该函数创建单例后台作业协调。 代码尝试确保指定实例 ID 仅存在一个活动实例。

[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;
    }
}

注释

前面的 C# 代码适用于独立辅助角色模型,这是建议用于.NET应用的模型。 有关进程内模型与隔离工作器模型之间差异的更多信息,请参阅 Durable Functions 版本一文。

以下示例演示如何使用持久任务 SDK 创建单例编排。 代码尝试确保指定实例 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 创建新实例。

协调器函数本身可以使用任何模式:启动和完成的标准函数,或持续运行的 永久协调。 单一实例模式仅控制并发运行的实例数。

后续步骤