Sdílet prostřednictvím


Problémy a přístupy ke správě verzí v Durable Functions (Azure Functions)

Je nevyhnutelné, že funkce budou přidány, odebrány a změněny v průběhu životnosti aplikace. Durable Functions umožňuje zřetězení funkcí různými způsoby, které nebyly dříve možné, a tento řetězení ovlivňuje způsob zpracování správy verzí.

Typy zásadních změn

Existuje několik příkladů zásadních změn, o které je potřeba vědět. Tento článek popisuje nejběžnější. Hlavním motivem za všemi z nich je, že změny kódu funkce ovlivňují jak nové, tak stávající orchestrace funkcí.

Změna signatur funkcí aktivit nebo entit

Změna podpisu odkazuje na změnu názvu, vstupu nebo výstupu funkce. Pokud se u nějaké aktivity nebo funkce entity provede tato změna, může dojít k narušení jakékoli funkce orchestrátoru, která na ní závisí. To 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.

Předpokládejme například, že máme následující funkci orchestrátoru.

[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    await context.CallActivityAsync("Bar", result);
}

Tato zjednodušená funkce přebírá výsledky Foo a předává je do Bar. Předpokládejme, že potřebujeme 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:

[FunctionName("FooBar")]
public static 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 se v tomto okamžiku nasadí změna podpisu, instance kontrolního bodu selže okamžitě po obnovení a přehrání volání Foo. K tomuto selhání dochází, protože výsledek v tabulce historie je boolean hodnota, ale nový kód se pokusí deserializovat ji do textového řetězce, což vede k neočekávanému chování nebo dokonce k výjimce během běhu programu pro jazyky s kontrolou typů.

Tento příklad je jen jedním z mnoha různých 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ěna logiky orchestrátoru

Jiná skupina problémů souvisejících s verzováním pochází ze změny kódu funkce orchestrátoru způsobem, který změní trasu vykonání pro běžící instance.

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

[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool result = await context.CallActivityAsync<bool>("Foo");
    await context.CallActivityAsync("Bar", result);
}

Teď předpokládejme, že chcete provést změnu pro přidání nového volání funkce mezi dvě existující volání funkce.

[FunctionName("FooBar")]
public static 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 SendNotification mezi Foo a Bar. Neexistují žádné změny podpisu. K problému dochází, když se existující instance obnoví z volání na Bar. Pokud během přehrávání původní volání Foo vrátilo true, přehrání orchestrátoru vyvolá SendNotification, což není v historii provádění. Modul runtime zjistí tuto nekonzistenci a vyvolá chybu nedeterministické orchestrace, protože místo očekávaného volání na Bar došlo k nečekanému volání SendNotification. 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, volání dílčích orchestrací atd.

Strategie zmírnění rizik

Tady jsou některé strategie pro řešení problémů se správou verzí:

  • Nic nedělejte (nedoporučuje se)
  • Verzování orchestrace (doporučeno ve většině případů)
  • Zastavte všechny instance za běhu
  • Souběžná nasazení

Nic nedělejte

Naivní přístup ke správě verzí spočívá v tom, že nic neděláte a necháte aktivní instance orchestrace selhat. V závislosti na typu změny může dojít k následujícím typům selhání.

  • Orchestrace může selhat s chybou nedeterministické orchestrace.
  • Orchestrace se můžou trvale zablokovat a hlásit Running stav.
  • Pokud se funkce odebere, může jakákoli funkce, která se ji pokusí volat, selhat s chybou.
  • Pokud se funkce po naplánování k provedení odebere, aplikace může zaznamenat selhání na nízké úrovni během běhu v enginu Durable Task Framework, což může vést k závažnému snížení výkonu.

Kvůli těmto potenciálním selháním se strategie "nic nedělá" nedoporučuje.

Správa verzí orchestrace

Poznámka:

Verzování orchestrace je aktuálně ve veřejné testovací verzi.

Funkce verzování orchestrací umožňuje, aby různé verze orchestrací spoluexistovaly a spouštěly se souběžně bez konfliktů a problémů s nedeterminismem, což umožňuje nasadit aktualizace a současně umožnit dokončení probíhajících instancí orchestrací bez ručního zásahu.

S verzováním orchestrace:

  • Každá instance orchestrace získá verzi, která k ní bude trvale přidružena při vytváření.
  • Funkce orchestratoru můžou odpovídajícím způsobem zkoumat jejich verzi a spouštění větví.
  • Pracovní procesy s novějšími verzemi funkcí orchestratoru můžou pokračovat ve spouštění instancí orchestrace vytvořených staršími verzemi.
  • Modul runtime brání pracovníkům, kteří používají starší verze funkcí orchestratoru, aby spouštěly orchestrace novějších verzí.

Tato strategie se doporučuje 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 viz verze orchestrace v Durable Functions.

Zastavte všechny instance za běhu

Další možností je zastavit všechny instance v letu. Pokud používáte výchozího poskytovatele Azure Storage pro Durable Functions, zastavení všech instancí lze provést vymazáním obsahu interních front control-queue a workitem-queue. Alternativně můžete zastavit Function App, odstranit tyto fronty a znovu aplikaci restartovat. Fronty se po restartování aplikace automaticky znovu vytvoří. Předchozí instance orchestrace můžou zůstat ve stavu Spuštěno po neomezenou dobu, ale nebudou zaplnit vaše protokoly zprávami o selhání ani nepoškodí vaši aplikaci. Tento přístup je ideální pro rychlý vývoj prototypů, včetně místního vývoje.

Poznámka:

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

Souběžná nasazení

Nejbezpečnější způsob, jak zajistit bezpečné nasazení zásadních změn, je jejich nasazením souběžně se staršími verzemi. Můžete to provést pomocí některé z následujících technik:

  • Nasaďte všechny aktualizace jako zcela nové funkce a ponechte stávající funkce as-is. Nedoporučuje se to obecně kvůli složitosti spojené s rekurzivní aktualizací, kdy je potřeba aktualizovat volající u nových verzí funkcí.
  • Nasaďte všechny aktualizace jako novou aplikaci funkcí s jiným účtem úložiště.
  • Nasaďte novou kopii aplikace funkcí se stejným účtem úložiště, ale s aktualizovaným názvem centra úloh . Výsledkem je vytvoření nových artefaktů úložiště, které můžou používat nová verze vaší aplikace. Stará verze vaší aplikace bude nadále fungovat s dříve uloženými objekty úložiště.

Souběžné nasazení je doporučená technika pro nasazení nových verzí vašich funkčních aplikací.

Poznámka:

Tyto pokyny pro strategii nasazení vedle sebe používají podmínky specifické pro Azure Storage, ale obecně platí pro všechny podporované poskytovatele úložiště Durable Functions.

Sloty nasazení

Při souběžných nasazeních ve službě Azure Functions nebo Azure App Service doporučujeme nasadit novou verzi aplikace funkcí do nového slotu nasazení. Sloty nasazení umožňují spustit několik kopií funkční aplikace vedle sebe, přičemž pouze jeden z nich je aktivním produkčním slotem. Až budete připraveni nasadit novou logiku orchestrace do stávající infrastruktury, může být tak jednoduché jako nasazení nové verze na produkční slot.

Poznámka:

Tato strategie funguje nejlépe, když pro funkce orchestrátoru používáte triggery HTTP a webhooku. U triggerů jiných než HTTP, jako jsou fronty nebo Event Hubs, by definice triggeru měla být odvozena z nastavení aplikace , které se aktualizuje jako součást operace prohození.

Další kroky