長期工作中的單一執行個體協調器

對於背景工作,您通常需要確保特定協調器一次只執行一個執行個體,以防止重複的協調流程同時執行。 你可以在 Durable Functions 或 Durable Task SDK 中實作這個單例模式,方法是在建立 orchestrator 時指派特定實例 ID,然後在啟動新實例前確認該 ID 實例是否已經在執行。

本文將說明如何實作單例編排器,並針對每種支援語言提供程式碼範例。

Prerequisites

備註

單一執行個體模式可能會有競爭條件。 如果兩個用戶端同時執行檢查與啟動邏輯,兩個呼叫可能都報告成功,但實際上只有一個編排實例會啟動。 根據您的需求,這可能會有不良副作用。 若需嚴格的單一實例保證,建議加入額外的鎖定機制。

這很重要

目前,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 版本條目。

下列範例示範如何使用 Durable Task SDK 建立 Singleton 協調流程。 程式碼嘗試確保指定實例 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 的新實例。

編排器函式本身可以使用任何模式——一個開始並完成的標準函式,或是持續運行的 永恆協調 。 單例模式僅控制同時執行的實例數量。

下一步