Co je Durable Functions?

Durable Functions je rozšíření Azure Functions, které umožňuje psát stavové funkce v bez serveru výpočetního prostředí. Toto rozšíření umožňuje definovat stavové pracovní postupy zápisem funkcí orchestrátoru a stavových entit tak, že pomocí programovacího modelu Azure Functions entity. Na pozadí rozšíření spravuje stav, kontrolní body a restartování, takže se můžete soustředit na obchodní logiku.

Podporované jazyky

Durable Functions aktuálně podporuje následující jazyky:

  • C#: jak předkompilované knihovny tříd, tak skript jazyka C#.
  • JavaScript: podporováno pouze pro verzi 2.x nebo novější Azure Functions runtime. Vyžaduje verzi 1.7.0 Durable Functions nebo novější verzi.
  • Python: vyžaduje verzi 2.3.1 Durable Functions nebo novější verzi.
  • F#: předkompilované knihovny tříd a skript jazyka F#. Skript F# se podporuje pouze pro verzi 1.x modulu Azure Functions runtime.
  • PowerShell: Podporováno pouze pro verzi 3.x modulu runtime Azure Functions a PowerShellu 7. Vyžaduje verzi 2.x rozšíření sady.

Pokud chcete získat přístup k nejnovějším funkcím a aktualizacím, doporučujeme použít nejnovější verze rozšíření Durable Functions a knihovny specifické pro Durable Functions jazyka. Další informace o Durable Functions verzích.

Durable Functions má za cíl podporovat všechny Azure Functions jazyky. V seznamu Durable Functions najdete nejnovější stav práce, který podporuje další jazyky.

Podobně Azure Functions existují šablony, které vám pomůžou s vývojem Durable Functions pomocí Visual Studio 2019, Visual Studio Codea Azure Portal.

Vzory aplikací

Hlavním případem použití pro Durable Functions je zjednodušení složitých stavových požadavků na koordinaci v aplikacích bez serveru. Následující části popisují typické vzory aplikací, které těží z Durable Functions:

Vzor č. 1: Řetězení funkcí

Ve vzoru zřetězování funkcí se posloupnost funkcí provádí v určitém pořadí. V tomto vzoru se výstup jedné funkce použije na vstup jiné funkce.

Diagram vzoru řetězení funkcí

Můžete použít Durable Functions k implementaci modelu řetězení funkcí výstižně, jak je znázorněno v následujícím příkladu.

V tomto příkladu jsou hodnoty , , a názvy jiných funkcí F1 F2 ve stejné aplikaci F3 F4 funkcí. Tok řízení můžete implementovat pomocí běžných imperativních konstruktorů kódování. Kód se spouští shora dolů. Kód může zahrnovat existující sémantiku toku řízení jazyka, jako jsou podmíněné výrazy a smyčky. Logiku zpracování chyb můžete zahrnout do try / catch / finally bloků.

[FunctionName("Chaining")]
public static async Task<object> Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    try
    {
        var x = await context.CallActivityAsync<object>("F1", null);
        var y = await context.CallActivityAsync<object>("F2", x);
        var z = await context.CallActivityAsync<object>("F3", y);
        return  await context.CallActivityAsync<object>("F4", z);
    }
    catch (Exception)
    {
        // Error handling or compensation goes here.
    }
}

Pomocí parametru můžete vyvolat další funkce podle názvu, předat parametry a context vrátit výstup funkce. Pokaždé, když kód zavolá metodu , Durable Functions framework zkontroluje await průběh aktuální instance funkce. Pokud se proces nebo virtuální počítač v polovině provádění recykluje, instance funkce se obnoví z předchozího await volání. Další informace najdete v další části Pattern 2: Fan out/fan in .

Vzor č. 2: Počet vějířů/ventilátorů

Ve vzoru fan out/fan in spustíte paralelně několik funkcí a pak čekáte na dokončení všech funkcí. Často se agregační práce provádí na výsledcích, které funkce vrací.

Diagram vzoru ventilátoru/ventilátoru

S normálními funkcemi můžete funkci roztáčet tak, že do fronty odešle více zpráv. Vrátit se do systému je mnohem náročnější. Chcete-li použít funkci fan in, v normální funkci napíšete kód, který bude sledovat, kdy skončí funkce aktivované frontou, a pak uložíte výstupy funkce.

Rozšíření Durable Functions zpracovává tento vzor s relativně jednoduchým kódem:

[FunctionName("FanOutFanIn")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var parallelTasks = new List<Task<int>>();

    // Get a list of N work items to process in parallel.
    object[] workBatch = await context.CallActivityAsync<object[]>("F1", null);
    for (int i = 0; i < workBatch.Length; i++)
    {
        Task<int> task = context.CallActivityAsync<int>("F2", workBatch[i]);
        parallelTasks.Add(task);
    }

    await Task.WhenAll(parallelTasks);

    // Aggregate all N outputs and send the result to F3.
    int sum = parallelTasks.Sum(t => t.Result);
    await context.CallActivityAsync("F3", sum);
}

Práce s rozdělením se distribuuje do několika instancí F2 funkce. Práce se sleduje pomocí dynamického seznamu úkolů. Task.WhenAll se volá , aby se čekalo na dokončení všech vvaných funkcí. Výstupy F2 funkce se pak agregují ze seznamu dynamických úloh a předá se F3 do funkce.

Automatické kontrolní body, ke které dochází při volání , zajistí, že při možném středním selhání nebo restartování nebude nutné restartovat již await Task.WhenAll dokončenou úlohu.

Poznámka

Ve výjimečných případech může dojít k chybě v okně po dokončení funkce aktivity, ale před jejím dokončením do historie orchestrace. Pokud k tomu dojde, funkce aktivity se po obnovení procesu znovu spustí od začátku.

Vzor č. 3: Asynchronní rozhraní API HTTP

Vzor asynchronního protokolu HTTP API řeší problém koordinace stavu dlouhotrvajících operací s externími klienty. Běžný způsob implementace tohoto modelu je, že koncový bod HTTP spustí dlouhotrvající akci. Pak přesměrujte klienta na koncový bod stavu, který se klient dotazuje, když se operace dokončí.

Diagram vzoru HTTP API

Durable Functions poskytuje integrovanou podporu pro tento model, což zjednodušuje nebo odebírá kód, který je potřeba napsat pro interakci s dlouhotrvajícím spouštěním funkcí. Například ukázky pro rychlý Start Durable Functions (C# a JavaScript) ukazují jednoduchý příkaz REST, který můžete použít ke spuštění nových instancí funkcí nástroje Orchestrator. Po spuštění instance rozšíření zpřístupňuje rozhraní API HTTP Webhooku, která se dotazují na stav funkce nástroje Orchestrator.

Následující příklad ukazuje příkazy REST, které spouštějí nástroj Orchestrator a dotazují svůj stav. Pro přehlednost jsou některé podrobnosti protokolu z příkladu vynechány.

> curl -X POST https://myfunc.azurewebsites.net/api/orchestrators/DoWork -H "Content-Length: 0" -i
HTTP/1.1 202 Accepted
Content-Type: application/json
Location: https://myfunc.azurewebsites.net/runtime/webhooks/durabletask/instances/b79baf67f717453ca9e86c5da21e03ec

{"id":"b79baf67f717453ca9e86c5da21e03ec", ...}

> curl https://myfunc.azurewebsites.net/runtime/webhooks/durabletask/instances/b79baf67f717453ca9e86c5da21e03ec -i
HTTP/1.1 202 Accepted
Content-Type: application/json
Location: https://myfunc.azurewebsites.net/runtime/webhooks/durabletask/instances/b79baf67f717453ca9e86c5da21e03ec

{"runtimeStatus":"Running","lastUpdatedTime":"2019-03-16T21:20:47Z", ...}

> curl https://myfunc.azurewebsites.net/runtime/webhooks/durabletask/instances/b79baf67f717453ca9e86c5da21e03ec -i
HTTP/1.1 200 OK
Content-Length: 175
Content-Type: application/json

{"runtimeStatus":"Completed","lastUpdatedTime":"2019-03-16T21:20:57Z", ...}

Vzhledem k tomu, že modul runtime Durable Functions spravuje stav za vás, nemusíte implementovat vlastní mechanismus pro sledování stavu.

Rozšíření Durable Functions zpřístupňuje Vestavěná rozhraní API HTTP, která spravují dlouhotrvající orchestrace. Tento vzor můžete případně implementovat sami pomocí triggerů funkcí (například HTTP, front nebo Azure Event Hubs) a vazby klienta Orchestration. Můžete například použít zprávu fronty k aktivaci ukončení. nebo můžete použít trigger HTTP, který je chráněný pomocí Azure Active Directory zásad ověřování místo integrovaných rozhraní api http, která pro ověřování používají vygenerovaný klíč.

Další informace najdete v článku funkce protokolu HTTP , který vysvětluje, jak můžete vystavit asynchronní a dlouhotrvající procesy přes protokol HTTP pomocí rozšíření Durable Functions.

Vzor #4: monitorování

Model monitorování odkazuje na flexibilní a opakovaný proces v pracovním postupu. Příkladem je cyklické dotazování, dokud nebudou splněny určité podmínky. Pomocí pravidelné aktivační procedury časovače můžete vyřešit základní scénář, například úlohu pravidelného čištění, ale jeho interval je statický a Správa životnosti instance je složitá. Pomocí Durable Functions můžete vytvářet flexibilní intervaly opakování, spravovat životnost úloh a vytvářet více procesů monitorování z jedné orchestrace.

Příkladem vzoru monitorování je vrácení dřívějšího scénáře asynchronního protokolu HTTP API. Místo vystavení koncového bodu pro externího klienta za účelem monitorování dlouhotrvající operace používá dlouhotrvající monitor externí koncový bod a poté čeká na změnu stavu.

Diagram modelu monitoru

V několika řádcích kódu můžete pomocí Durable Functions vytvořit více monitorů, které sledují libovolné koncové body. Monitory mohou ukončit provádění, pokud je splněna podmínka, nebo jiná funkce může použít trvalého klienta Orchestration k ukončení monitorování. Můžete změnit interval monitorování na wait základě konkrétní podmínky (například exponenciální omezení rychlosti.)

Následující kód implementuje základní monitor:

[FunctionName("MonitorJobStatus")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    int jobId = context.GetInput<int>();
    int pollingInterval = GetPollingInterval();
    DateTime expiryTime = GetExpiryTime();

    while (context.CurrentUtcDateTime < expiryTime)
    {
        var jobStatus = await context.CallActivityAsync<string>("GetJobStatus", jobId);
        if (jobStatus == "Completed")
        {
            // Perform an action when a condition is met.
            await context.CallActivityAsync("SendAlert", machineId);
            break;
        }

        // Orchestration sleeps until this time.
        var nextCheck = context.CurrentUtcDateTime.AddSeconds(pollingInterval);
        await context.CreateTimer(nextCheck, CancellationToken.None);
    }

    // Perform more work here, or let the orchestration end.
}

Po přijetí žádosti se pro ID úlohy vytvoří nová instance Orchestration. Instance se dotazuje na stav, dokud není splněna podmínka a dojde k ukončení smyčky. Interval cyklického dotazování řídí trvalý časovač. Pak je možné provést více práce, nebo orchestrace může skončit. Když nextCheck se překročí expiryTime , monitor skončí.

Vzor #5: interakce člověka

Řada automatizovaných procesů zahrnuje nějaký druh lidské interakce. Zapojení lidí do automatizovaného procesu je obtížné, protože lidé nejsou jako vysoce dostupné a reagují jako cloudové služby. Automatizovaný proces může pro tuto interakci umožňovat pomocí časových limitů a logiky kompenzace.

Schvalovací proces je příkladem obchodního procesu, který zahrnuje lidskou interakci. Pro sestavu výdajů, která překračuje určitou částku dolaru, může být vyžadováno schválení správcem. Pokud správce neschválí zprávu o výdajích do 72 hodin (možná správce přešel na dovolenou), proces eskalace se zahájí a získá schválení od někoho jiného (možná správce manažera).

Diagram vzoru lidské interakce

Vzor v tomto příkladu můžete implementovat pomocí funkce Orchestrator. Nástroj Orchestrator používá k žádosti o schválení trvalý časovač . Pokud dojde k vypršení časového limitu, produkt Orchestrator postoupí. Orchestrator čeká na externí událost, jako je například oznámení, které vygenerovala lidská interakce.

Tyto příklady vytvoří proces schvalování, který předvádí vzor lidské interakce:

[FunctionName("ApprovalWorkflow")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    await context.CallActivityAsync("RequestApproval", null);
    using (var timeoutCts = new CancellationTokenSource())
    {
        DateTime dueTime = context.CurrentUtcDateTime.AddHours(72);
        Task durableTimeout = context.CreateTimer(dueTime, timeoutCts.Token);

        Task<bool> approvalEvent = context.WaitForExternalEvent<bool>("ApprovalEvent");
        if (approvalEvent == await Task.WhenAny(approvalEvent, durableTimeout))
        {
            timeoutCts.Cancel();
            await context.CallActivityAsync("ProcessApproval", approvalEvent.Result);
        }
        else
        {
            await context.CallActivityAsync("Escalate", null);
        }
    }
}

Chcete-li vytvořit trvalý časovač, zavolejte context.CreateTimer . Oznámení přijal (a) context.WaitForExternalEvent . Pak Task.WhenAny se zavolá, aby se rozhodlo, jestli se má eskalovat (časový limit nastane jako první), nebo jestli se má schválit schválení (schválení se přijme před časovým limitem)

Externí klient může doručovat oznámení události do čekající funkce Orchestrator pomocí integrovaných rozhraní API http:

curl -d "true" http://localhost:7071/runtime/webhooks/durabletask/instances/{instanceId}/raiseEvent/ApprovalEvent -H "Content-Type: application/json"

Událost se dá taky vyvolat pomocí trvalého klienta Orchestration z jiné funkce ve stejné aplikaci Function App:

[FunctionName("RaiseEventToOrchestration")]
public static async Task Run(
    [HttpTrigger] string instanceId,
    [DurableClient] IDurableOrchestrationClient client)
{
    bool isApproved = true;
    await client.RaiseEventAsync(instanceId, "ApprovalEvent", isApproved);
}

Vzor #6: agregátor (stavové entity)

Šestým vzorem je informace o agregaci dat událostí v časovém intervalu až na jednu, adresovatelnou entitu. V tomto modelu mohou být shromážděná data z více zdrojů, mohou být dodávána v dávkách nebo mohou být rozmístěna za dlouhou dobu. Agregátor může potřebovat provést akci s daty události při jejich doručení a externí klienti budou potřebovat dotaz na agregovaná data.

Agregátorový diagram

Důvodem, proč se pokusit o implementaci tohoto modelu s normálními a bezstavovým funkcemi, je, že řízení souběžnosti se stává obrovským problémem. Nemusíte si dělat starosti s více vlákny, které mění stejná data současně, musíte se také starat o to, že agregátor běží jenom na jednom virtuálním počítači.

Můžete použít trvalé entity k jednoduché implementaci tohoto modelu jako jediné funkce.

[FunctionName("Counter")]
public static void Counter([EntityTrigger] IDurableEntityContext ctx)
{
    int currentValue = ctx.GetState<int>();
    switch (ctx.OperationName.ToLowerInvariant())
    {
        case "add":
            int amount = ctx.GetInput<int>();
            ctx.SetState(currentValue + amount);
            break;
        case "reset":
            ctx.SetState(0);
            break;
        case "get":
            ctx.Return(currentValue);
            break;
    }
}

Odolné entity lze také modelovat jako třídy v rozhraní .NET. Tento model může být užitečný, pokud je seznam operací pevný a bude velký. Následující příklad je ekvivalentní implementace Counter entity pomocí tříd a metod .NET.

public class Counter
{
    [JsonProperty("value")]
    public int CurrentValue { get; set; }

    public void Add(int amount) => this.CurrentValue += amount;

    public void Reset() => this.CurrentValue = 0;

    public int Get() => this.CurrentValue;

    [FunctionName(nameof(Counter))]
    public static Task Run([EntityTrigger] IDurableEntityContext ctx)
        => ctx.DispatchAsync<Counter>();
}

Klienti mohou zařadit operace do fronty (označované také jako "signalizace") entity funkce pomocí vazby klienta entit.

[FunctionName("EventHubTriggerCSharp")]
public static async Task Run(
    [EventHubTrigger("device-sensor-events")] EventData eventData,
    [DurableClient] IDurableEntityClient entityClient)
{
    var metricType = (string)eventData.Properties["metric"];
    var delta = BitConverter.ToInt32(eventData.Body, eventData.Body.Offset);

    // The "Counter/{metricType}" entity is created on-demand.
    var entityId = new EntityId("Counter", metricType);
    await entityClient.SignalEntityAsync(entityId, "add", delta);
}

Poznámka

Dynamicky generované proxy servery jsou také k dispozici v rozhraní .NET pro signalizaci entit v typově bezpečném způsobu. Kromě signalizace se klienti můžou také dotazovat na stav funkce entity pomocí typově bezpečných metod na vazbu klienta Orchestration.

Funkce entit jsou k dispozici v Durable Functions 2,0 a vyšších pro jazyky C#, JavaScript a Python.

Technologie

na pozadí je rozšíření Durable Functions postaveno na trvalých architekturách úloh, open source knihovně na GitHub, která se používá k sestavování pracovních postupů v kódu. Podobně jako Azure Functions je vývoj Azure WebJobs bez serveru, Durable Functions je vývojem trvalého prostředí úloh bez serveru. Microsoft a další organizace často využívají trvalý rámec úloh pro automatizaci nejdůležitějších procesů. Pro prostředí Azure Functions bez serveru je to přirozené.

Omezení kódu

Za účelem zajištění spolehlivých a dlouhotrvajících záruk spouštění mají funkce nástroje Orchestrator sadu pravidel pro kódování, která musí být dodržena. Další informace naleznete v článku o omezeních kódu funkce nástroje Orchestrator .

Fakturace

Durable Functions se účtují stejně jako Azure Functions. Další informace najdete v tématu Azure Functions ceny. Při provádění funkcí Orchestrator v plánu Azure Functions spotřebyexistují některá nastavení fakturace, o kterých je potřeba vědět. Další informace o tomto chování najdete v článku o fakturaci Durable Functions .

Skok přímo v

Můžete začít s Durable Functions za 10 minut, a to provedením jednoho z těchto kurzů pro rychlý Start pro konkrétní jazyk:

V těchto rychlých startech se místně vytváří a testuje trvalá funkce Hello World. Kód funkce potom publikujete do Azure. Funkce, kterou vytváříte, orchestruje a řetězí volání dalších funkcí.

Tisk

Durable Functions se vyvíjí ve spolupráci s Microsoft Research. V důsledku toho tým Durable Functions aktivně vytváří výzkumné doklady a artefakty; mezi ně patří:

Další informace

Následující video zvýrazní výhody Durable Functions:

Podrobnější diskuzi o Durable Functions a základní technologii najdete v následujícím videu (zaměřuje se na .NET, ale koncepty platí i pro jiné podporované jazyky):

Vzhledem k tomu, že Durable Functions je pokročilá rozšíření pro Azure Functions, není vhodné pro všechny aplikace. Porovnání s dalšími technologiemi orchestrace Azure najdete v tématu porovnání Azure functions a Azure Logic Apps.

Další kroky