Durable Functions 中的单一实例业务流程协调程序 (Azure Functions)Singleton orchestrators in Durable Functions (Azure Functions)

对于后台作业,通常需要确保一次只运行特定业务流程协调程序的一个实例。For background jobs, you often need to ensure that only one instance of a particular orchestrator runs at a time. 通过在创建业务流程协调程序时将特定实例 ID 分配给该业务流程协调程序,可以确保 Durable Functions 中的这种单一实例行为。You can ensure this kind of singleton behavior in Durable Functions by assigning a specific instance ID to an orchestrator when creating it.

单一实例示例Singleton example

以下示例显示了一个 HTTP 触发器函数,该函数创建一个单一实例后台作业业务流程。The following example shows an HTTP-trigger function that creates a singleton background job orchestration. 该代码可确保只存在一个具有指定实例 ID 的实例。The code ensures that only one instance exists for a specified instance ID.

[FunctionName("HttpStartSingle")]
public static async Task<HttpResponseMessage> RunSingle(
    [HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}/{instanceId}")] HttpRequestMessage req,
    [DurableClient] IDurableOrchestrationClient starter,
    string functionName,
    string instanceId,
    ILogger log)
{
    // Check if an instance with the specified ID already exists or an existing one stopped running(completed/failed/terminated).
    var existingInstance = await starter.GetStatusAsync(instanceId);
    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.
        dynamic eventData = await req.Content.ReadAsAsync<object>();
        await starter.StartNewAsync(functionName, instanceId, eventData);
        log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
        return starter.CreateCheckStatusResponse(req, instanceId);
    }
    else
    {
        // An instance with the specified ID exists or an existing one still running, don't create one.
        return new HttpResponseMessage(HttpStatusCode.Conflict)
        {
            Content = new StringContent($"An instance with ID '{instanceId}' already exists."),
        };
    }
}

备注

前面的 C# 代码适用于 Durable Functions 2.x。The previous C# code is for Durable Functions 2.x. 对于 Durable Functions 1.x,必须使用 OrchestrationClient 属性而不是 DurableClient 属性,并且必须使用 DurableOrchestrationClient 参数类型,而不是 IDurableOrchestrationClientFor Durable Functions 1.x, you must use OrchestrationClient attribute instead of the DurableClient attribute, and you must use the DurableOrchestrationClient parameter type instead of IDurableOrchestrationClient. 有关版本之间差异的详细信息,请参阅 Durable Functions 版本一文。For more information about the differences between versions, see the Durable Functions versions article.

默认情况下,实例 ID 是随机生成的 GUID。By default, instance IDs are randomly generated GUIDs. 但是,在前面的示例中,实例 ID 通过 URL 在路由数据中传递。In the previous example, however, the instance ID is passed in route data from the URL. 该代码调用 GetStatusAsync (C#) 或 getStatus (JavaScript) 检查具有指定 ID 的实例是否已在运行。The code calls GetStatusAsync(C#) or getStatus (JavaScript) to check if an instance having the specified ID is already running. 如果没有此类实例正在运行,将使用该 ID 创建一个新实例。If no such instance is running, a new instance is created with that ID.

备注

在此示例中有潜在的争用条件。There is a potential race condition in this sample. 如果 HttpStartSingle 的两个实例同时执行,则两个函数调用都将报告成功,但实际上只会启动一个业务流程实例。If two instances of HttpStartSingle execute concurrently, both function calls will report success, but only one orchestration instance will actually start. 根据你的要求,这可能会产生不良副作用。Depending on your requirements, this may have undesirable side effects. 因此,必须确保没有两个请求可以同时执行此触发器函数。For this reason, it is important to ensure that no two requests can execute this trigger function concurrently.

业务流程协调程序函数的实现细节实际上无关紧要。The implementation details of the orchestrator function don't actually matter. 它可以是一个启动并完成的常规业务流程协调程序函数,也可以是一个永远运行的业务流程协调程序函数(即永久业务流程)。It could be a regular orchestrator function that starts and completes, or it could be one that runs forever (that is, an Eternal Orchestration). 重点是一次只有一个实例在运行。The important point is that there is only ever one instance running at a time.

后续步骤Next steps