Singleton vezénylők a Durable Taskben

Háttérfeladatok esetén gyakran gondoskodnia kell arról, hogy egy adott orchestratornak csak egy példánya fusson egyszerre, hogy megelőzze az ismétlődő vezénylések egyidejű futását. Ezt az egytonos mintát a Durable Functions vagy a Durable Task SDK-kban implementálhatja úgy, hogy egy adott példányazonosítót rendel egy vezénylőhöz a létrehozáskor, majd ellenőrzi, hogy az adott azonosítóval rendelkező példány már fut-e az új példány indítása előtt.

Ez a cikk bemutatja, hogyan implementálhatók önálló vezénylők az egyes támogatott nyelvekre vonatkozó kód példáival.

Prerequisites

Megjegyzés:

Lehetséges versenyállapot van a singleton mintában. Ha két ügyfél egyszerre hajtja végre az ellenőrzési és indítási logikát, mindkét hívás sikeres lehet, de valójában csak egy vezénylési példány indul el. A követelményektől függően ez nemkívánatos mellékhatásokat okozhat. Ha szigorú egypéldányos garanciákra van szükség, fontolja meg további zárolási mechanizmusok hozzáadását.

Fontos

A PowerShell Durable Task SDK jelenleg nem érhető el.

Példa singleton orkchestrációra

Az alábbi példa egy HTTP-trigger függvényt mutat be, amely egyetlen háttérfeladat-vezénylést hoz létre. A kód megkísérli biztosítani, hogy csak egy aktív példány létezik egy adott példányazonosítóhoz.

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

Megjegyzés:

Az előző C#-kód az izolált feldolgozói modellhez tartozik, amely .NET alkalmazásokhoz ajánlott modell. A folyamatban levő és az izolált munkásmodellek közötti különbségekről további információt a Durable Functions verziók cikkben talál.

Az alábbi példa bemutatja, hogyan hozhat létre szingelton vezénylést a Durable Task SDK használatával. A kód megkísérli biztosítani, hogy csak egy aktív példány létezik egy adott példányazonosítóhoz.

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

A singleton minta működése

Mivel a példányazonosítók egyediek a feladatközpontban, az ismert, rögzített azonosítóval rendelkező vezénylés ütemezése és állapotának ellenőrzése először megakadályozza az egyidejű futtatások duplikálását. Alapértelmezés szerint a példányazonosítók véletlenszerűen generált GUID-ok. Az előző példákban azonban egy adott példányazonosító lesz átadva. A kód ezután lekéri az orchestrációs példány metaadatait annak ellenőrzésére, hogy az adott azonosítóval rendelkező példány már fut-e. Ha nem fut ilyen példány, a rendszer új példányt hoz létre ezzel az azonosítóval.

Maga a vezénylő függvény bármilyen mintát használhat – egy alapfüggvényt, amely elindul és befejeződik, vagy egy folyamatosan futó örök vezénylést . A szingleton minta csak azt szabályozza, hogy hány példány fusson egyszerre.

Következő lépések