Orchestrátory s jednímtonem v Durable Task

U úloh na pozadí často potřebujete zajistit, aby současně běžela jenom jedna instance konkrétního orchestrátoru, což brání souběžnému spuštění duplicitních orchestrací. Tento model singleton můžete implementovat v Durable Functions nebo v Durable Task SDKs tím, že mu při jeho vytváření přiřadíte konkrétní ID instance orchestrátoru a pak zkontrolujete, jestli již s tímto ID instance běží, než spustíte nový.

Tento článek ukazuje, jak implementovat orchestrátory s jednímtonem s příklady kódu pro každý podporovaný jazyk.

Předpoklady

Poznámka:

Je zde potenciální podmínka soutěže v singleton vzoru. Pokud dva klienti spouští logiku kontroly a spuštění souběžně, můžou obě volání hlásit úspěch, ale ve skutečnosti se spustí pouze jedna instance orchestrace. V závislosti na vašich požadavcích to může mít nežádoucí vedlejší účinky. Pokud jsou vyžadovány přísné záruky na jedinečnost instance, zvažte přidání dalších uzamykacích mechanismů.

Důležité

V současné době není sada POWERShell Durable Task SDK dostupná.

Příklad singleton orchestrátoru

Následující příklad ukazuje funkci aktivovanou HTTP, která vytvoří orchestraci úloh na pozadí jako singleton. Kód se pokusí zajistit, že pro zadané ID instance existuje pouze jedna aktivní instance.

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

Poznámka:

Předchozí kód jazyka C# je určený pro izolovaný model pracovního procesu, což je doporučený model pro .NET aplikace. Další informace o rozdílech mezi modely pracovního procesu a izolovaných pracovních modelů najdete v článku verze Durable Functions.

Následující příklad ukazuje, jak vytvořit singletonní orchestraci pomocí SDKs pro Durable Task. Kód se pokusí zajistit, že pro zadané ID instance existuje pouze jedna aktivní instance.

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.");
}

Jak funguje singletonový vzor

Vzhledem k tomu, že ID instancí jsou v centru úloh jedinečná, plánování orchestrace se známým, pevným ID a kontrolou stavu nejprve brání duplicitním souběžným spuštěním. Ve výchozím nastavení jsou ID instancí náhodně generované GUIDy. V předchozích příkladech se však předá konkrétní ID instance. Kód pak načte metadata instance orchestrace a zkontroluje, jestli je instance s tímto ID již spuštěná. Pokud taková instance není spuštěná, vytvoří se s tímto ID nová instance.

Samotná funkce orchestrátoru může používat libovolný vzor – standardní funkci, která se spouští a dokončí, nebo věčnou orchestraci , která běží nepřetržitě. Vzor singleton pouze kontroluje, kolik instancí běží současně.

Další kroky