Verzování orchestrace

Nasazení změn logiky orchestrátoru je klíčovým aspektem při práci s trvalými systémy orchestrace. Pokud se orchestrace přeruší a později obnoví (například během aktualizace hostitele), modul runtime znovu přehraje události orchestrace a před provedením dalšího kroku zajistí úspěšné provedení všech předchozích kroků. Pokud se kód orchestrace mezi nasazeními změnil, kroky, které provádí, už nemusí být stejné. V takovém případě systém vyhodí chybu nedeterminismu místo toho, aby dovolil orchestrace pokračovat.

Správa verzí orchestrace zabraňuje problémům souvisejícím s nedeterminismu, což umožňuje bezproblémovou práci s novými (nebo starými) orchestracemi při zachování deterministického modelu spouštění, který trvalá orchestrace vyžaduje.

Tato integrovaná funkce poskytuje automatickou izolaci verzí s minimální konfigurací. Je nezávislá na back-endu, takže ji může používat libovolná aplikace využívající některý z poskytovatelů Durable Functions storage, včetně plánovače úloh Durable Task Scheduler.

Sady DURABLE Task SDK podporují dva styly správy verzí, které můžete použít samostatně nebo společně:

Terminologie

Tento článek používá dva související, ale odlišné termíny:

  • Funkce orchestratoru (nebo jednoduše orchestrátor): Kód funkce, který definuje logiku pracovního postupu – šablonu nebo podrobný plán pro způsob provádění pracovního postupu.
  • Instance orchestrace (nebo jednoduše "orchestrace"): Konkrétní spuštění funkce orchestrátoru s vlastním stavem, ID instance a vstupy. Více instancí orchestrace může běžet souběžně ze stejné funkce orchestrátoru.

Pochopení tohoto rozdílu je zásadní pro řízení verzí orchestrace. Kód funkce orchestrátoru obsahuje logiku podporující verzi, zatímco instance orchestrace jsou při vytváření trvale přidruženy ke konkrétní verzi.

Jak to funguje

Správa verzí orchestrace funguje na těchto základních principech:

  • Přidružení verze: Když se vytvoří instance orchestrace, je k ní trvale přidružena verze.
  • Spouštění s podporou verzí: Kód orchestrátoru zkoumá hodnotu verze přidruženou k aktuální instanci orchestrace a podle toho rozdělí provádění.
  • Zpětná kompatibilita: Pracovní procesy s novějšími verzemi orchestrátoru nadále spouštějí instance orchestrace vytvořené staršími verzemi.
  • Ochrana dopředu: Modul runtime zabraňuje pracovníkům se staršími verzemi orchestrátoru spouštět orchestrace, které byly zahájeny novějšími verzemi.

V praxi nastavíte v klientovi výchozí řetězec verze (nebo v host.json pro Durable Functions) a kód orchestrátoru používá context.Version k větvení mezi starou a novou logikou.

Předpoklady

Před použitím správy verzí orchestrace se ujistěte, že máte požadované verze balíčků pro váš programovací jazyk.

Pokud používáte jiný jazyk než .NET (JavaScript, Python, PowerShell nebo Java) se sadami extension bundle, musí vaše aplikace funkcí odkazovat na Extension Bundle verze 4.30.0 nebo novější. Nakonfigurujte rozsah extensionBundle v host.json, aby minimální verze byla alespoň 4.30.0. Například:

{
    "version": "2.0",
    "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle",
        "version": "[4.30.0, 5.0.0)"
    }
}

Podrobnosti o výběru a aktualizaci verzí sad najdete v dokumentaci ke konfiguraci sady rozšíření.

Kromě požadavku na sadu rozšíření pro jiné než .NET jazyky musíte také použít minimální verzi balíčku SDK specifického pro jazyk, který je uvedený níže. Aby správa verzí orchestrace fungovala správně, vyžaduje se sada rozšíření i balíček SDK.

Použijte Microsoft.Azure.Functions.Worker.Extensions.DurableTask verzi 1.14.0 nebo novější.

Nastavení výchozí verze

Pokud chcete používat správu verzí orchestrace, nejprve nakonfigurujte výchozí verzi pro nové instance orchestrace.

Do souboru defaultVersion v projektu Azure Functions přidejte nebo aktualizujte nastavení host.json:

{
  "extensions": {
    "durableTask": {
      "defaultVersion": "<version>"
    }
  }
}

Řetězec verze může postupovat podle libovolného formátu, který vyhovuje vaší strategii správy verzí:

  • Vícečástové verzování: "1.0.0", "2.1.0"
  • Jednoduché číslování: "1", "2"
  • Na základě data: "2025-01-01"
  • Vlastní formát: "v1.0-release"

Po nastavení defaultVersionjsou všechny nové instance orchestrace trvale přidružené k této verzi.

Při konfiguraci aplikace nastavte výchozí verzi v tvůrci klienta.

Poznámka:

K dispozici v sadě .NET SDK (Microsoft.DurableTask.Client.AzureManaged) od verze 1.9.0.

builder.Services.AddDurableTaskClient(builder =>
{
    builder.UseDurableTaskScheduler(connectionString);
    builder.UseDefaultVersion("1.0.0");
});

Tato verze je jednoduchý řetězec a může přijmout libovolnou hodnotu. Sada SDK se pokusí převést na .NET System.Version. V případě úspěchu se tato knihovna použije k porovnání. V opačném případě se použije jednoduché porovnání řetězců.

Po nastavení výchozí verze v klientovi se veškerá orchestrace spuštěná tímto klientem trvale přidružuje k této verzi. Verze je dostupná také v kontextu orchestrace, takže ji můžete použít v podmíněných příkazech.

Pravidla porovnání verzí

Pokud je vybrána strategie Strict nebo CurrentOrOlder (viz Shoda verzí), runtime porovná verzi instance orchestrace s hodnotou defaultVersion workeru podle následujících pravidel:

  • Prázdné nebo null verze jsou považovány za stejné.
  • Prázdná nebo null verze je považována za starší než jakákoli definovaná verze.
  • Pokud jsou obě verze číselné (například "1.0" a "2.0"), porovnají se jako čísla verzí, takže "2.0" je novější než "1.0".
  • V opačném případě se provede porovnání řetězců bez rozlišování malých a velkých písmen.

Následující příklady ukazují, jak funguje porovnání verzí:

Verze A Verze B Výsledek
"1.0" "2.0" A je starší
null "1.0" A je starší
null null Rovný
"v1-release" "v2-release" A je starší (řazení abecední)

Pokud je vybrána strategie Strict shody nebo CurrentOrOlder (viz Shoda verzí), porovnání verzí závisí na jazyce:

  • .NET: SDK se pokusí analyzovat verzi jako System.Version. Pokud jsou obě analýzy úspěšně provedeny, porovnání použije CompareTo. V opačném případě sada SDK používá porovnání řetězců.
  • Python: Sada SDK používá packaging.version k porovnání sémantických verzí.
  • Java: SDK porovnává verzi jako jednoduchý řetězec.

Logika orchestratoru pracující s verzemi

Pokud chcete implementovat logiku podporující verzi, použijte kontextový parametr pro přístup k verzi a spuštění větve aktuální instance orchestrace.

Důležité

Při implementaci logiky podporující verze je důležité zachovat přesnou logiku orchestrátoru pro starší verze. Jakékoli změny v sekvenci, pořadí nebo podpisu volání aktivit pro stávající verze mohou narušit deterministické přehrání a způsobit selhání probíhajících orchestrací nebo vést k nesprávným výsledkům. Po nasazení ponechte cesty kódu staré verze nezměněné.

[Function("MyOrchestrator")]
public static async Task<string> RunOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    if (context.Version == "1.0")
    {
        // Original logic for version 1.0
        ...
    }
    else if (context.Version == "2.0")
    {
        // New logic for version 2.0
        ...
    }
    ...
}
[DurableTask]
class HelloCities : TaskOrchestrator<string, List<string>>
{
    private readonly string[] Cities = ["Seattle", "Amsterdam", "Hyderabad"];

    public override async Task<List<string>> RunAsync(
        TaskOrchestrationContext context, string input)
    {
        List<string> results = [];
        foreach (var city in Cities)
        {
            results.Add(await context.CallSayHelloAsync($"{city} v{context.Version}"));
            if (context.CompareVersionTo("2.0.0") >= 0)
            {
                results.Add(await context.CallSayGoodbyeAsync($"{city} v{context.Version}"));
            }
        }
        return results;
    }
}

Poznámka:

Vlastnost context.Version je jen pro čtení a odráží verzi, která je trvale přidružena k instanci orchestrace při jejím vytvoření. Tuto hodnotu nelze během provádění orchestrace změnit.

Návod

Pokud už máte orchestrace v testovací verzi vytvořené před určením výchozí verze, context.Version vrátí pro tyto instance hodnotu null (nebo ekvivalent závislý na jazyce). Strukturujte logiku orchestrátoru tak, aby zpracovávala jak starší (nulovou verzi), tak i nové verzované orchestrace.

Chování nasazení

Tady je, co očekávat, když nasadíte aktualizovanou funkci orchestrátoru s logikou nové verze:

  • Koexistence pracovního procesu: Spustí se nový kód funkce orchestrátoru, zatímco někteří pracovníci se starým kódem jsou potenciálně stále aktivní.
  • Přiřazení verze pro nové instance: Všechny nové orchestrace a dílčí orchestrace vytvořené novými pracovníky získají přiřazené verzi od defaultVersion.
  • Kompatibilita nových pracovních procesů: Nové pracovní procesy můžou zpracovávat nově vytvořené orchestrace i dříve existující orchestrace, protože logika větvení pracující s verzemi zajišťuje zpětnou kompatibilitu.
  • Omezení starých pracovníků: Staří pracovníci můžou zpracovávat pouze orchestrace s verzí rovnající se nebo nižší než verze zadaná v jejich vlastní defaultVersionhost.json, protože se neočekává, že by jejich kód orchestrátoru byl kompatibilní s novějšími verzemi.

Poznámka:

Správa verzí orchestrace nemá vliv na životní cyklus pracovníka. Platforma Azure Functions spravuje nastavení a vyřazení pracovních procesů z provozu na základě běžných pravidel v závislosti na modelech hostování.

Příklad: Nahrazení aktivity v posloupnosti

Tento příklad ukazuje, jak nahradit aktivitu uprostřed sekvence pomocí verzování orchestrace.

Verze 1.0

konfiguracehost.json:

{
  "extensions": {
    "durableTask": {
      "defaultVersion": "1.0"
    }
  }
}

Funkce Orchestrator:

[Function("ProcessOrderOrchestrator")]
public static async Task<string> ProcessOrder(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    var orderId = context.GetInput<string>();

    await context.CallActivityAsync("ValidateOrder", orderId);
    await context.CallActivityAsync("ProcessPayment", orderId);
    await context.CallActivityAsync("ShipOrder", orderId);

    return "Order processed successfully";
}

Verze 2.0 se zpracováním slev

konfiguracehost.json:

{
  "extensions": {
    "durableTask": {
      "defaultVersion": "2.0"
    }
  }
}

Funkce Orchestrator:

[Function("ProcessOrderOrchestrator")]
public static async Task<string> ProcessOrder(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    var orderId = context.GetInput<string>();

    await context.CallActivityAsync("ValidateOrder", orderId);

    if (TaskOrchestrationVersioningUtils.CompareVersions(context.Version, "1.0") <= 0)
    {
        // Preserve original logic for existing instances
        await context.CallActivityAsync("ProcessPayment", orderId);
    }
    else
    {
        // New logic with discount processing
        await context.CallActivityAsync("ApplyDiscount", orderId);
        await context.CallActivityAsync("ProcessPaymentWithDiscount", orderId);
    }

    await context.CallActivityAsync("ShipOrder", orderId);

    return "Order processed successfully";
}

Porovnávání verzí

Strategie sladění verzí určuje, které instance orchestrace pracovník zpracovává na základě kompatibility verzí.

Následující tabulka popisuje dostupné strategie:

Strategie Description
Nic Při zpracování se verze nebere v úvahu. Veškerá práce se zpracovává bez ohledu na verzi.
Striktní Verze orchestrace a verze pracovního procesu se musí přesně shodovat.
CurrentOrOlder Verze orchestrace musí být stejná nebo menší než verze pracovníka. Toto je výchozí strategie.

Konfigurace

{
  "extensions": {
    "durableTask": {
      "defaultVersion": "<version>",
      "versionMatchStrategy": "CurrentOrOlder"
    }
  }
}
  • None (nedoporučuje se): Zakáže kontrolu verzí. Jakýkoliv pracovní proces může zpracovávat kteroukoliv instanci orchestrace.
  • Strict: Zpracovává úlohy pouze z orchestrací se stejnou verzí jako defaultVersion. Vyžaduje pečlivou koordinaci nasazení, aby nedocházelo ke vzniku neintegrovaných orchestrací.
  • CurrentOrOlder (výchozí): Zpracovává úlohy z orchestrací s verzí menší nebo rovnou defaultVersion. Umožňuje zpětnou kompatibilitu a brání starším pracovníkům ve zpracování novějších orchestrací.

Nakonfigurujte strategii shody prostřednictvím tvůrce pracovních procesů.

Poznámka:

K dispozici v sadě .NET SDK (Microsoft.DurableTask.Worker.AzureManaged) již od verze 1.9.0.

builder.Services.AddDurableTaskWorker(builder =>
{
    builder.AddTasks(r => r.AddAllGeneratedTasks());
    builder.UseDurableTaskScheduler(connectionString);
    builder.UseVersioning(new DurableTaskWorkerOptions.VersioningOptions
    {
        Version = "1.0.0",
        DefaultVersion = "1.0.0",
        MatchStrategy = DurableTaskWorkerOptions.VersionMatchStrategy.Strict,
        FailureStrategy = DurableTaskWorkerOptions.VersionFailureStrategy.Reject,
    });
});

Zpracování neshod verzí

Strategie zpracování neshod verzí určuje, co se stane, když verze instance orchestrace neodpovídá verzi pracovního procesu.

Následující tabulka popisuje dostupné strategie:

Strategie Description
Odmítat Orchestrace je odmítnuta a vrácena do pracovní fronty. Jiný pracovník ho může později zkusit. Tato strategie je výchozí.
Fail Orchestrace se nezdařila a byla odebrána z pracovní fronty.

Konfigurace

{
  "extensions": {
    "durableTask": {
      "defaultVersion": "<version>",
      "versionFailureStrategy": "Reject"
    }
  }
}
  • Reject (výchozí): Orchestrace instance zůstává v aktuálním stavu a lze ji znovu spustit později, jakmile bude k dispozici kompatibilní pracovník. Tato strategie je nejbezpečnější volbou, protože zachovává stav orchestrace.
  • Fail: Okamžitě ukončí instanci orchestrace se stavem selhání. Tato možnost může být vhodná, pokud neshoda verzí značí vážné problémy s nasazením.

Kdy použít každou strategii

Odmítnout: Tuto strategii použijte, pokud chcete, aby orchestrace zkusil později nebo v jiném pracovním procesu. Reject Během selhání:

  1. Orchestrace je odmítnuta a vrácena do pracovní fronty.
  2. Jiný pracovník vyřadí orchestrace z fronty.
  3. Vyřazená orchestrace by mohla opět přistát na jiném pracovníkovi nebo na stejném.

Proces se opakuje, dokud není k dispozici pracovník, který dokáže zvládnout orchestraci. Tato strategie bezproblémově zpracovává postupné nasazování, kde se pracovní procesy postupně aktualizují.

Chyba: Tuto strategii použijte, když není očekáváno, že orchestraci zpracuje žádná jiná verze pracovníka. Orchestrace selže a přejde do terminálního stavu.

Poznámka:

Nakonfigurujte strategii selhání prostřednictvím FailureStrategy vlastnosti v možnostech správy verzí, jak je znázorněno v ukázkách kódu odpovídajících verzím .

Zahájení orchestrací s konkrétními verzemi

Ve výchozím nastavení všechny nové instance orchestrace používají aktuální defaultVersion zadaný v host.json konfiguraci. Můžete ale mít scénáře, ve kterých potřebujete vytvořit orchestrace s konkrétní verzí, která se liší od aktuálního výchozího nastavení.

Kdy použít konkrétní verze

  • Postupná migrace: Pokračujte ve vytváření orchestrace se starší verzí i nadále po nasazení novější verze.
  • Testovací scénáře: Testování chování konkrétních verzí v produkčním prostředí
  • Situace vrácení zpět: Dočasně se vraťte k vytváření instancí s předchozí verzí.
  • Pracovní postupy specifické pro jednotlivé verze: Různé obchodní procesy vyžadují různé verze orchestrace.
[Function("HttpStart")]
public static async Task<HttpResponseData> HttpStart(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
    [DurableClient] DurableTaskClient client,
    FunctionContext executionContext)
{
    var options = new StartOrchestrationOptions
    {
        Version = "1.0"
    };

    string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(
        "ProcessOrderOrchestrator", orderId, options);
    // ...
}

V rámci funkce orchestrátoru můžete také spustit dílčí orchestrace s konkrétními verzemi:

[Function("MainOrchestrator")]
public static async Task<string> RunMainOrchestrator(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    var subOptions = new SubOrchestratorOptions
    {
        Version = "1.0"
    };

    var result = await context.CallSubOrchestratorAsync<string>(
        "ProcessPaymentOrchestrator", orderId, subOptions);
    // ...
}

Odstranit zastaralé části kódu

V průběhu času můžete chtít z funkcí orchestrátoru odebrat starší cesty kódu, abyste zjednodušili údržbu a snížili technický dluh. Odeberte kód pečlivě, abyste se vyhnuli přerušení existujících instancí orchestrace.

Pokud je bezpečné odebrat starší verzi kódu

  • Všechny instance orchestrace používající starou verzi byly dokončeny (úspěšné, neúspěšné nebo ukončené).
  • Ve staré verzi se nevytvoří žádné nové instance orchestrace.
  • Zkontrolovali jste pomocí monitorování nebo dotazování, že ve zastaralé verzi nejsou spuštěné žádné instance.
  • Dostatek časového období uplynulo od posledního nasazení staré verze.

Pokud chcete zkontrolovat spuštěné instance, použijte rozhraní API pro správu instancí k dotazování orchestrací podle stavu a ověřte, že ve staré verzi stále neběží žádná.

Pokud chcete zkontrolovat spuštěné instance, použijte DurableTaskClient seznam instancí orchestrace filtrovaných podle stavu a ověřte, že ve staré verzi stále neběží žádná instance.

Výstraha

Odebrání starých cest kódu může způsobit deterministické selhání při opakování, zatímco instance orchestrace stále běží tyto verze. Před odebráním kódu vždy zkontrolujte, že žádné instance nepoužívají starší verzi.

Osvědčené postupy

Správa verzí

  • Použití vícedílné správy verzí: Přijetí konzistentního schématu správy verzí, například major.minor.patch.
  • Zásadní změny dokumentu: Jasně zdokumentujte, jaké změny vyžadují novou verzi.
  • Plánování životního cyklu verzí: Definujte, kdy odebrat legacy cesty kódu.

Organizace kódu

  • Samostatná logika verze: Pro různé verze použijte jasné větvení nebo samostatné metody.
  • Zachování determinismu: Po nasazení neupravujte existující logiku verze. Pokud jsou změny naprosto nezbytné, například kritické opravy chyb, zajistěte, aby zachovaly deterministické chování a nezměnily posloupnost operací.
  • Důkladně otestujte: Otestujte všechny cesty verzí, zejména během přechodů.

Monitorování a pozorovatelnost

  • Informace o verzi protokolu: Zahrňte verzi do protokolování, aby se usnadnilo ladění.
  • Monitorování distribuce verzí: Sledujte, které verze aktivně běží.
  • Nastavení upozornění: Monitorujte případné chyby související s verzí.

Troubleshooting

Běžné problémy

  • Problém: Instance orchestrace vytvořené s verzí 1.0 selhávají po nasazení verze 2.0

    • Řešení: Ujistěte se, že cesta kódu verze 1.0 v orchestrátoru zůstane úplně stejná. Jakékoli změny v sekvenci provádění můžou narušit deterministické přehrání.
  • Problém: Pracovníci se staršími verzemi orchestrace nemohou spouštět nové orchestrace.

    • Řešení: Toto chování se očekává. Modul runtime zabraňuje starším pracovníkům ve spouštění orchestrací s novějšími verzemi. Ujistěte se, že jsou všichni pracovníci aktualizováni na nejnovější verzi a že je odpovídajícím způsobem aktualizováno jejich defaultVersion nastavení host.json .
  • Problém: Informace o verzi nejsou v orchestrátoru dostupné (hodnota context.Version nebo context.getVersion() je nulová bez ohledu na nastavení defaultVersion).

    • Řešení: Zkontrolujte část Požadavky a ujistěte se, že vaše prostředí splňuje všechny požadavky na správu verzí orchestrace.
  • Problém: Orchestrace novější verze jsou velmi pomalé nebo jsou zablokované

    • Řešení: Tento problém může mít různé původní příčiny:
      1. Nedostatek novějších pracovníků: Ujistěte se, že je nasazeno a aktivní dostatečné množství pracovníků, kteří obsahují stejnou nebo vyšší verzi defaultVersion.
      2. Rušení směrování orchestrace staršími pracovníky: Starší pracovníci mohou rušit mechanismus směrování orchestrace, což ztěžuje novým pracovníkům převzetí orchestrace. Tato interference může být obzvláště patrná u některých poskytovatelů úložiště (Azure Storage nebo MSSQL). Za normálních okolností platforma Azure Functions zajišťuje, aby staré pracovníky byly ukončeny brzy po nasazení, takže jakékoli zpoždění obvykle není významné. Zvažte použití Plánovače trvalých úloh pro vylepšený mechanismus směrování.

Troubleshooting

Běžné problémy

  • Problém: Orchestrace se zablokují nebo neprobíhá po nasazení nové verze.

    • Řešení: Ověřte, že MatchStrategy a FailureStrategy jsou správně nakonfigurované v možnostech správy verzí pracovního procesu. Pokud používáte Strict porovnávání, tyto odpovídající orchestrace můžou zpracovávat pouze pracovníci se úplně stejnou verzí. Přepněte na CurrentOrOlder , pokud potřebujete zpětnou kompatibilitu.
  • Problém: orchestrace selhávají okamžitě kvůli chybě neshody verzí

    • Řešení: Zkontrolujte, zda je FailureStrategy nastaveno na Fail. Pokud ano, orchestrace, které neodpovídají žádné dostupné verzi pracovního procesu, vstoupí do konečného stavu selhání. Použijte Reject místo toho, aby orchestraci umožnil zůstat ve frontě, dokud nebude k dispozici kompatibilní pracovník.
  • Problém: context.Version vrací None/null/undefined pro instance orchestrace.

    • Řešení: Orchestrace vytvořené před konfigurací výchozí verze nemají přiřazenou verzi. Ujistěte se, že logika orchestrátoru zpracovává null nebo prázdné hodnoty verzí jako logiku staršího kódu.

::: konec-zóny