Výzvy k vytváření verzí a strategie zmírnění rizik v Durable Functions

Správa verzí v Durable Functions je nezbytná, protože funkce se v průběhu životnosti aplikace nutně přidávají, odebírají a mění. Durable Functions umožňuje zřetězit funkce způsoby, které nebyly dříve možné, a tento řetězení ovlivňuje způsob zpracování správy verzí.

Tento článek vám pomůže:

Rychlé porovnání strategie

Pokud už víte, že vaše změna je problémová, použijte tuto tabulku k výběru strategie zmírnění:

Strategy Nejlepší pro Podrobnosti
Verzování orchestrace (doporučeno) Většina aplikací s zásadními změnami Integrovaná funkce běhového prostředí funguje s jakýmkoli úložným backendem. Přejít na sekci
Souběžná nasazení Aplikace, které nemůžou používat správu verzí orchestrace nebo které potřebují úplnou izolaci prostřednictvím samostatných center úloh nebo účtů úložiště. Přejít na sekci
Zastavte všechny aktuálně běžící instance Vytváření prototypů a místní vývoj, kde je přijatelné ztráty orchestrací v testovacích verzích. Přejít na sekci

Tip

Pokud hledáte integrovanou funkci správy verzí orchestrace, která poskytuje automatickou izolaci verzí na úrovni runtime, podívejte se na Správa verzí orchestrace.

Important

Před nasazením zkontrolujte, jestli se jedná o zásadní změnu:

  • Změnili jste název, typ vstupu nebo výstupní typ aktivity nebo funkce entity?
  • Přidali jste , odebrali nebo přeuspořádali volání aktivit, dílčích orchestrací, časovačů nebo externích událostí v kódu orchestrátoru?
  • Přejmenovali jste nebo odebrali funkci, kterou můžou orchestrace v testovacích verzích pořád volat?

Pokud jste na některou z těchto možností odpověděli ano , použijte některou z níže uvedených strategií pro zmírnění rizik , abyste se vyhnuli chybám při spouštění orchestrací.

Typy zásadních změn

Existuje několik příkladů zásadních změn. Tento článek popisuje nejběžnější typy. Hlavním motivem všech z nich je, že změny kódu funkce ovlivňují nové i stávající orchestrace funkcí.

Změny podpisu funkce aktivity nebo entity

Změna podpisu odkazuje na změnu názvu, vstupu nebo výstupu funkce. Pokud provedete tuto změnu aktivity nebo funkce entity, může dojít k narušení jakékoli funkce orchestrátoru, která na ní závisí. Toto chování platí zejména pro typově bezpečné jazyky. Pokud aktualizujete funkci orchestrátoru tak, aby vyhovovala této změně, můžete přerušit stávající instance v testovacích verzích.

Jako příklad zvažte následující funkci orchestrátoru.


Izolovaný model pracovního procesu
[Function("FooBar")]
public static async Task Run([OrchestrationTrigger] TaskOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    await context.CallActivityAsync("Bar", result);
}

Model v probíhajícím procesu
[FunctionName("FooBar")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    await context.CallActivityAsync("Bar", result);
}

Tato funkce převezme výsledek Foo a předá ho Bar. Předpokládejme, že potřebujete změnit návratovou hodnotu foo z logické hodnoty na řetězec, aby podporovala širší škálu výsledných hodnot. Výsledek vypadá takto:


Izolovaný model pracovního procesu
[Function("FooBar")]
public static async Task Run([OrchestrationTrigger] TaskOrchestrationContext context)
{
    string result = await context.CallActivityAsync<string>("Foo");
    await context.CallActivityAsync("Bar", result);
}

Model v probíhajícím procesu
[FunctionName("FooBar")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string result = await context.CallActivityAsync<string>("Foo");
    await context.CallActivityAsync("Bar", result);
}

Tato změna funguje správně pro všechny nové instance funkce orchestrátoru, ale může narušit všechny instance v testovacích verzích. Představte si například případ, kdy instance orchestrace volá funkci s názvem Foo, získá zpět logickou hodnotu a pak kontrolní body. Pokud je v tomto okamžiku nasazena změna podpisu, instance kontrolního bodu selže okamžitě, když se obnoví a znovu přehraje volání Foo. K tomuto selhání dochází, protože výsledkem tabulky historie je Boolean hodnota, ale nový kód se pokusí deserializovat do řetězcové hodnoty, což vede k neočekávanému chování nebo dokonce běhové výjimce pro typově bezpečné jazyky.

Tento příklad je jedním z mnoha způsobů, jak může změna podpisu funkce narušit existující instance. Obecně platí, že pokud orchestrátor potřebuje změnit způsob, jakým volá funkci, bude změna pravděpodobně problematická.

Změny logiky orchestratoru

Další třídou problémů s verzováním je změna kódu funkce orchestrátoru způsobem, který změní cestu provádění pro právě běžící instance.

Zvažte následující funkci orchestrátoru:


Izolovaný model pracovního procesu
[Function("FooBar")]
public static async Task Run([OrchestrationTrigger] TaskOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    await context.CallActivityAsync("Bar", result);
}

Model v probíhajícím procesu
[FunctionName("FooBar")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    await context.CallActivityAsync("Bar", result);
}

Nyní předpokládejme, že chcete přidat nové volání funkce mezi dvě existující volání funkce.


Izolovaný model pracovního procesu
[Function("FooBar")]
public static async Task Run([OrchestrationTrigger] TaskOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    if (result)
    {
        await context.CallActivityAsync("SendNotification");
    }

    await context.CallActivityAsync("Bar", result);
}

Model v probíhajícím procesu
[FunctionName("FooBar")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    if (result)
    {
        await context.CallActivityAsync("SendNotification");
    }

    await context.CallActivityAsync("Bar", result);
}

Tato změna přidá nové volání funkce mezi SendNotificationFoo a Bar. Neexistují žádné změny podpisu. K problému dochází, když se existující instance vrátí z volání do Bar. Pokud původní volání Foo během přehrávání vrátilo true, pak orchestrátor přehraje volání do SendNotification, která není v historii provádění. Modul runtime zjistí tento nesoulad a vyvolá chybu nedeterministické orchestrace, protože místo očekávaného volání SendNotification došlo k volání Bar. Ke stejnému typu problému může dojít při přidávání volání rozhraní API do jiných trvalých operací, jako je vytváření trvalých časovačů, čekání na externí události nebo volání dílčích orchestrací.

Strategie zmírnění rizik

Warning

Nasazení zásadních změn bez strategie zmírnění rizik (přístup "nic nedělat") může způsobit selhání orchestrací s nedeterministickými chybami orchestrace , uvíznout natrvalo ve Running stavu nebo aktivovat selhání modulu runtime nízké úrovně, které snižují výkon. Při nasazování zásadních změn vždy používejte jednu z následujících strategií.

Na rozdíl od ostatních strategií v této části je správa verzí orchestrace integrovanou funkcí modulu runtime , která poskytuje automatickou izolaci verzí. Nemusíte spravovat samostatná nasazení, centra úloh ani účty úložiště. Místo toho modul runtime sleduje informace o verzi a zajišťuje, aby instance orchestrace byly zpracovány kompatibilními pracovními procesy.

S verzováním orchestrace:

  • Každá instance orchestrace získá trvale přiřazenou verzi k ní při vytváření.
  • Funkce orchestratoru mohou podle toho zkoumat svou verzi a řídit provádění větví a zároveň udržovat staré a nové větve kódu ve stejné základně kódu.
  • Pracovníci používající novější verze orchestrátorových funkcí mohou pokračovat ve spouštění instancí orchestrace vytvořených staršími verzemi.
  • Modul runtime zabraňuje pracovníkům, kteří používají starší verze funkcí orchestratoru, aby spouštěly orchestrace novějších verzí.

Tento přístup vyžaduje minimální konfiguraci (řetězec verze a volitelnou strategii shody) a je kompatibilní s jakýmkoli poskytovatelem úložiště. Jedná se o doporučenou strategii pro aplikace, které potřebují podporovat zásadní změny při zachování nasazení s nulovými výpadky.

Podrobné pokyny k konfiguraci a implementaci najdete v tématu Správa verzí orchestrace.

Zastavte všechny instance za běhu

Další možností je zastavit všechny instance v letu. Pokud používáte poskytovatele Azure Storage for Durable Functions, zastavte všechny instance vymazáním obsahu interní fronty control-queue a workitems-queue. Případně zastavte aplikaci pro funkce, odstraňte tyto fronty a restartujte aplikaci. Fronty se po restartování aplikace automaticky znovu vytvoří. Předchozí instance orchestrace mohou zůstat ve stavu Running neomezeně dlouho, ale nezahlcují vaše logy selháním ani nezpůsobují žádnou škodu vaší aplikaci. Tento přístup je ideální pro rychlý vývoj prototypů, včetně místního vývoje.

Warning

Tento přístup vyžaduje přímý přístup k podkladovým prostředkům úložiště a není vhodný pro všechny poskytovatele úložiště podporované Durable Functions.

Souběžná nasazení

Nejspolehlivějším způsobem, jak zajistit jejich bezpečné nasazení zásadních změn, je jejich nasazení souběžně se staršími verzemi. Můžete použít některou z následujících technik:

  • Jiný účet úložiště: Nasaďte všechny aktualizace jako novou aplikaci funkcí s jiným účtem úložiště. Tím se plně izoluje stav nové verze od staré verze.
  • Jiné centrum úloh: Nasaďte novou kopii aplikace funkcí se stejným účtem úložiště, ale s aktualizovaným názvem centra úloh . Tento přístup vytvoří nové artefakty úložiště pro novou verzi, zatímco stará verze bude nadále používat své stávající artefakty.

Při souběžných nasazeních v Azure můžete použít sloty deployment pro souběžné spouštění obou verzí pouze s jednou jako aktivní slot production. Až budete připraveni zveřejnit novou logiku orchestrace, prohodte novou verzi do produkčního slotu.

Note

Tyto pokyny používají termíny specifické pro Azure Storage, ale obecně platí pro všechny podporované poskytovatele úložiště pro Durable Functions.

Note

Prohození slotů nasazení funguje nejlépe s triggery HTTP a webhooku. U ne-HTTP aktivačních událostí, jako jsou fronty nebo Event Hubs, by definice aktivační události měla být odvozena z nastavení aplikace, které se aktualizuje jako součást operace výměny.

Další kroky