Külső események kezelése tartós orchestrationökben

A külső események lehetővé teszik, hogy a futó vezénylések jeleket fogadjanak külső forrásokból – például emberi jóváhagyásokból, webhook-visszahívásokból vagy más rendszerekből. Ez a cikk bemutatja, hogyan várhatja meg, küldheti el és kezelheti a külső eseményeket a tartós orchestrationokban.

Jótanács

Eseményeket szeretne küldeni egy orchestrációra? Ugrás a(z) Események küldése felületre.

Az Orchestrator függvények várakozhatnak és figyelhetik a külső eseményeket. A Durable Functions ezen funkciója gyakran hasznos emberi interakciók vagy más külső eseményindítók kezelésére.

Megjegyzés:

A külső események egyirányú aszinkron műveletek. Nem alkalmasak olyan helyzetekre, amikor az eseményt küldő ügyfélnek szinkron választ kell kapnia a vezénylő függvénytől.

A vezénylések megvárhatják és meghallgathatják a külső eseményeket. Ez a funkció gyakran hasznos emberi interakciók vagy más külső eseményindítók kezelésére.

Megjegyzés:

A külső események egyirányú aszinkron műveletek. Nem alkalmasak olyan helyzetekre, amikor az eseményt küldő ügyfélnek szinkron válaszra van szüksége a vezényléstől.

Fontos

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

Várakozás külső eseményekre

A vezénylési trigger kötésének"wait-for-external-event" API-ja lehetővé teszi, hogy a vezénylő függvény aszinkron módon várja meg és figyelje a külső ügyfél által küldött eseményeket. A figyelő vezénylő függvény deklarálja az esemény nevét és a várható adatok alakját .

A "wait-for-external-event" API lehetővé teszi a vezénylést, hogy aszinkron módon várjon és figyelje a külső ügyfél által küldött eseményeket. A hallgatási vezérlés deklarálja az esemény nevét és a várhatóan fogadandó adatok strukturáját.

Izolált munkavállalói modell

using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask;
using Microsoft.Extensions.Logging;

public class BudgetApproval
{
    private readonly ILogger _logger;

    public BudgetApproval(ILoggerFactory loggerFactory)
    {
        _logger = loggerFactory.CreateLogger<BudgetApproval>();
    }

    [Function("BudgetApproval")]
    public async Task Run(
        [OrchestrationTrigger] TaskOrchestrationContext context)
    {
        bool approved = await context.WaitForExternalEventAsync<bool>("Approval");
        if (approved)
        {
            // approval granted - do the approved action
        }
        else
        {
            // approval denied - send a notification
        }
    }
}

Folyamaton belüli modell

[FunctionName("BudgetApproval")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool approved = await context.WaitForExternalEvent<bool>("Approval");
    if (approved)
    {
        // approval granted - do the approved action
    }
    else
    {
        // approval denied - send a notification
    }
}

Megjegyzés:

Ha Durable Functions 1.x-et használ, DurableOrchestrationContext helyett IDurableOrchestrationContext. További részleteket a Durable Functions verziók cikkben talál.

public class BudgetApproval : TaskOrchestrator<object?, bool>
{
    public override async Task<bool> RunAsync(TaskOrchestrationContext context, object? input)
    {
        bool approved = await context.WaitForExternalEvent<bool>("Approval");
        if (approved)
        {
            // approval granted - do the approved action
        }
        else
        {
            // approval denied - send a notification
        }
        return approved;
    }
}

Az előző példa egy adott eseményt figyel, és az esemény fogadásakor műveletet hajt végre.

Egyszerre több eseményt is figyelhet, például az alábbi példában, amely a három lehetséges eseményértesítés egyikére vár.

Izolált munkavállalói modell

[Function("Select")]
public async Task Run(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    Task<float> event1 = context.WaitForExternalEventAsync<float>("Event1");
    Task<bool> event2 = context.WaitForExternalEventAsync<bool>("Event2");
    Task<int> event3 = context.WaitForExternalEventAsync<int>("Event3");

    Task winner = await Task.WhenAny(event1, event2, event3);
    if (winner == event1)
    {
        // ...
    }
    else if (winner == event2)
    {
        // ...
    }
    else if (winner == event3)
    {
        // ...
    }
}

Folyamaton belüli modell

[FunctionName("Select")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var event1 = context.WaitForExternalEvent<float>("Event1");
    var event2 = context.WaitForExternalEvent<bool>("Event2");
    var event3 = context.WaitForExternalEvent<int>("Event3");

    var winner = await Task.WhenAny(event1, event2, event3);
    if (winner == event1)
    {
        // ...
    }
    else if (winner == event2)
    {
        // ...
    }
    else if (winner == event3)
    {
        // ...
    }
}

Megjegyzés:

A Durable Functions 1.x használatban van? Becserélése DurableOrchestrationContext helyett IDurableOrchestrationContext. A Durable Functions verziók cikkben további információt talál a verzióeltérésről.

public class SelectOrchestrator : TaskOrchestrator<object?, object?>
{
    public override async Task<object?> RunAsync(TaskOrchestrationContext context, object? input)
    {
        Task<float> event1 = context.WaitForExternalEvent<float>("Event1");
        Task<bool> event2 = context.WaitForExternalEvent<bool>("Event2");
        Task<int> event3 = context.WaitForExternalEvent<int>("Event3");

        Task winner = await Task.WhenAny(event1, event2, event3);
        if (winner == event1)
        {
            // ...
        }
        else if (winner == event2)
        {
            // ...
        }
        else if (winner == event3)
        {
            // ...
        }
        return null;
    }
}

Az előző példa több esemény bármelyikét figyeli. Az összes eseményt is megvárhatja.

Izolált munkavállalói modell

[Function("NewBuildingPermit")]
public async Task Run(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    string applicationId = context.GetInput<string>();

    Task gate1 = context.WaitForExternalEventAsync<object>("CityPlanningApproval");
    Task gate2 = context.WaitForExternalEventAsync<object>("FireDeptApproval");
    Task gate3 = context.WaitForExternalEventAsync<object>("BuildingDeptApproval");

    // all three departments must grant approval before a permit can be issued
    await Task.WhenAll(gate1, gate2, gate3);

    await context.CallActivityAsync("IssueBuildingPermit", applicationId);
}

Folyamaton belüli modell

[FunctionName("NewBuildingPermit")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string applicationId = context.GetInput<string>();

    var gate1 = context.WaitForExternalEvent("CityPlanningApproval");
    var gate2 = context.WaitForExternalEvent("FireDeptApproval");
    var gate3 = context.WaitForExternalEvent("BuildingDeptApproval");

    // all three departments must grant approval before a permit can be issued
    await Task.WhenAll(gate1, gate2, gate3);

    await context.CallActivityAsync("IssueBuildingPermit", applicationId);
}

Megjegyzés:

Amennyiben a Durable Functions 1.x-et futtatja, használja a DurableOrchestrationContext a IDurableOrchestrationContext helyett. Nézze meg a Durable Functions verziókat a verziók közötti különbségek részletes listájához.

A .NET-ben, ha az esemény hasznos adatai nem konvertálhatók a várt típusra T, a rendszer kivételt küld.

public class NewBuildingPermit : TaskOrchestrator<string, object?>
{
    public override async Task<object?> RunAsync(TaskOrchestrationContext context, string applicationId)
    {
        Task<object?> gate1 = context.WaitForExternalEvent<object?>("CityPlanningApproval");
        Task<object?> gate2 = context.WaitForExternalEvent<object?>("FireDeptApproval");
        Task<object?> gate3 = context.WaitForExternalEvent<object?>("BuildingDeptApproval");

        // all three departments must grant approval before a permit can be issued
        await Task.WhenAll(gate1, gate2, gate3);

        await context.CallActivityAsync("IssueBuildingPermit", applicationId);
        return null;
    }
}

A .NET-ben, ha az esemény hasznos adatai nem konvertálhatók a várt típusra T, a rendszer kivételt küld.

A "wait-for-external-event" API határozatlan ideig várakozik bizonyos bemenetekre. Amíg várakozik, biztonságosan leállíthatja a függvényalkalmazást. Amikor és ha egy esemény érkezik erre az orchestrációs példányra, a példány automatikusan felébred, és azonnal feldolgozza az eseményt.

Megjegyzés:

Ha a függvényalkalmazás a Használati csomagot használja, a rendszer nem számol fel számlázási díjakat, miközben egy vezénylő függvény egy külső eseményfeladatra vár, függetlenül attól, hogy mennyi ideig vár.

A Tevékenységfüggvényekhez hasonlóan a külső események is legalább egyszeri kézbesítési garanciával rendelkeznek. Ez azt jelenti, hogy bizonyos feltételek mellett (például újraindítások, skálázás, összeomlások stb.) az alkalmazás ugyanahhoz a külső eseményhez duplikátumokat kaphat. Ezért azt javasoljuk, hogy a külső események valamilyen azonosítót tartalmazzanak, amely lehetővé teszi, hogy manuálisan eltávolítsák a duplikátumokat az orchestration rendszerekben.

A "wait-for-external-event" API határozatlan ideig várakozik bizonyos bemenetekre. Várakozás közben biztonságosan leállíthatja a munkafolyamatot. Ha és amikor egy esemény érkezik erre a vezénylési példányra, a rendszer automatikusan felébred, és azonnal feldolgozza az eseményt.

A külső események legalább egyszer kézbesítési garanciával rendelkeznek. Ez azt jelenti, hogy bizonyos feltételek mellett (például újraindítások, skálázás, összeomlások stb.) az alkalmazás ugyanahhoz a külső eseményhez duplikátumokat kaphat. Ezért azt javasoljuk, hogy a külső események valamilyen azonosítót tartalmazzanak, amely lehetővé teszi a kettőzések manuális eltávolítását az orchestration folyamatokban.

Események küldése

A vezénylési ügyfél kötés által definiált "raise-event" API használatával külső eseményt küldhet egy vezénylésnek. A beépített eseményindító HTTP API segítségével külső eseményt is küldhet egy orkesztrációhoz.

Az emelt esemény tartalmaz egy instanceID, egy eventNameés eventData paramétert is. Az Orchestrator függvények az API-k használatával kezelik ezeket az wait-for-external-event eseményeket. Az eventName esemény feldolgozásához meg kell egyeznie mind a küldési , mind a fogadási végeken. Az eseményadatoknak JSON-szerializálhatónak is kell lenniük.

A "raise-event" mechanizmusok belsőleg egy üzenetet idéznek elő, amelyet a várakozó vezénylő függvény fog át. Ha a példány nem a megadott eseménynévre vár, az eseményüzenet hozzáadódik egy memóriabeli üzenetsorhoz. Ha a vezénylési példány később elkezdi figyelni az esemény nevét, ellenőrzi az üzenetsort az eseményüzenetek esetében.

Megjegyzés:

Ha nincs orchesztrációs példány a megadott példányazonosítóval, az eseményüzenet elvetésre kerül.

Az alábbiakban egy sorra aktivált függvény látható, amely egy "Jóváhagyási" eseményt küld egy orchestrator függvénypéldánynak. A vezénylési példány azonosítója az üzenetsor üzenetének törzséből származik.

A Durable Task ügyfélen a "raise-event" API használatával külső eseményt küldhet egy orchestration-re.

Az emelt esemény tartalmaz egy példányazonosítót, egy eventName és egy eventData paramétert. Az orchestrationok ezeket az eseményeket a "wait for external event" API-k használatával kezelik. Az eseménynévnek egyeznie kell mind a küldési, mind a fogadási végeken az esemény feldolgozásához. Az eseményadatoknak JSON-szerializálhatónak is kell lenniük.

A "raise-event" mechanizmusok belsőleg egy üzenetet sorba állítanak, amelyet a várakozó rendszerezés vesz fel. Ha a példány nem a megadott eseménynévre vár, a rendszer hozzáadja az eseményüzenetet egy memóriabeli üzenetsorhoz. Ha a vezénylési példány később elkezdi figyelni az esemény nevét, ellenőrzi az üzenetsort az eseményüzenetek esetében.

Megjegyzés:

Ha nincs vezénylési példány a megadott instanceID, a rendszer elveti az eseményüzenetet.

Az alábbi példa egy "Jóváhagyási" eseményt küld egy orkesztációs példánynak.

Izolált munkavállalói modell

using Microsoft.Azure.Functions.Worker;
using Microsoft.DurableTask.Client;

public class ApprovalQueueProcessor
{
    [Function("ApprovalQueueProcessor")]
    public async Task Run(
        [QueueTrigger("approval-queue")] string instanceId,
        [DurableClient] DurableTaskClient client)
    {
        await client.RaiseEventAsync(instanceId, "Approval", true);
    }
}

Folyamaton belüli modell

[FunctionName("ApprovalQueueProcessor")]
public static async Task Run(
    [QueueTrigger("approval-queue")] string instanceId,
    [DurableClient] IDurableOrchestrationClient client)
{
    await client.RaiseEventAsync(instanceId, "Approval", true);
}

Megjegyzés:

Az 1.x Durable Functions helyett használja a OrchestrationClient attribútumot és DurableOrchestrationClient paramétertípust. A Durable Functions verziók cikkben minden verzióspecifikus módosítást talál.

await client.RaiseEventAsync(instanceId, "Approval", true);

A "raise-event" API belsőleg egy üzenetet sorba állít, amelyet a várakozó orkestráció fog átvenni. Ha a példány nem a megadott eseménynévre vár, a rendszer hozzáadja az eseményüzenetet egy memóriabeli pufferhez. Ha a vezénylési példány később elkezdi figyelni az esemény nevét, ellenőrzi az eseményüzenetek pufferét, és aktiválja a rá váró feladatot.

Megjegyzés:

Ha nincs orchestration példány a megadott példányazonosítóval, a rendszer elveti az esemény üzenetet.

HTTP

Az alábbi példa egy HTTP-kérésre, amely Approval eseményt hoz létre egy "orchestrációs példány" számára.

POST /runtime/webhooks/durabletask/instances/MyInstanceId/raiseEvent/Approval&code=XXX
Content-Type: application/json

"true"

Ebben az esetben a példányazonosító a MyInstanceId kóddal van kódolva.

Bevált gyakorlatok

A külső események használatakor tartsa szem előtt az alábbi ajánlott eljárásokat:

Egyedi eseménynevek használata deduplikációhoz

A külső események legalább egyszer kézbesítési garanciával rendelkeznek. Bizonyos ritka körülmények között (amelyek újraindítások, skálázás vagy összeomlások során fordulhatnak elő) előfordulhat, hogy az alkalmazás ugyanannak a külső eseménynek duplikált példányait kapja. Javasoljuk, hogy a külső események egyedi azonosítót tartalmazzanak, amely lehetővé teszi azok kézzel történő deduplikálását az orchestration rendszerekben.

Megjegyzés:

A MSSQL-tárolószolgáltató külső eseményeket használ fel, és tranzakciósan frissíti a vezénylési állapotot, így a Azure Storage szolgáltatótól eltérően nem áll fenn ismétlődő események kockázata. Azonban továbbra is ajánlott, hogy a külső események egyedi névvel rendelkezzenek, hogy a kód a háttérrendszerek között is hordozható legyen.

Időtúllépések használata a határozatlan idejű várakozások elkerülése érdekében

Az wait-for-external-event API alapértelmezés szerint határozatlan ideig várakozik. A legtöbb valós forgatókönyvben – például az emberi jóváhagyások esetén – egy tartós időzítőt kell versenyeztetni a külső eseménnyel szemben, hogy az orchestráció intézkedhessen (eszkaláljon, elutasítson, újrapróbálkozzon), ha az esemény nem érkezik meg a határidőn belül.

A kódmintákkal kapcsolatos teljes útmutatóért tekintse meg az emberi interakciókat és időtúllépéseket.

Következő lépések