Share via


Orchestratieversiebeheer in Durable Functions (Azure Functions) - openbare proefversie

Orchestratieversiebeheer pakt de kernuitdaging aan bij het doorvoeren van wijzigingen in orchestratiefuncties, terwijl het deterministische uitvoeringsmodel wordt gehandhaafd dat Durable Functions vereist. Zonder deze functie zouden belangrijke wijzigingen in orchestratorlogica- of activiteitsfunctiehandtekeningen ervoor zorgen dat in-flight orchestration-exemplaren mislukken tijdens het opnieuw afspelen, omdat ze determinismevereiste zouden verbreken die zorgt voor een betrouwbare indelingsuitvoering. Deze ingebouwde functie biedt automatische versie-isolatie met minimale configuratie. Het is back-endneutraal, zodat deze kan worden gebruikt door apps die gebruikmaken van een van de opslagproviders van de Durable Function, inclusief de Durable Task Scheduler.

Note

Als u voor Durable Task Scheduler-gebruikers de Durable Task SDK's gebruikt in plaats van Durable Task Functions, raadpleegt u het artikel over het versiebeheer van Durable Task SDK's.

Terminology

In dit artikel worden twee gerelateerde maar afzonderlijke termen gebruikt:

  • Orchestratorfunctie (of gewoon orchestrator): verwijst naar de functiecode die de werkstroomlogica definieert: de sjabloon of blauwdruk voor de uitvoering van een werkstroom.
  • Orchestratie-exemplaar (of gewoon 'orchestration'): verwijst naar een specifieke uitvoering van een orchestratorfunctie, met een eigen status, instantie-ID en invoer. Meerdere orchestratie-exemplaren kunnen gelijktijdig worden uitgevoerd vanuit dezelfde orchestrator functie.

Het begrijpen van dit onderscheid is van cruciaal belang voor indelingsversiebeheer, waarbij de orchestratorfunctiecode versiebewuste logica bevat, terwijl indelingsexemplaren permanent worden gekoppeld aan een specifieke versie wanneer ze worden gemaakt.

Hoe het werkt

De orchestration versioning-functie werkt op basis van deze kernprincipes:

  • Versiekoppeling: Wanneer een orkestinstantie wordt gemaakt, wordt er permanent een versie aan gekoppeld.

  • Versiebewuste uitvoering: Orchestrator-functiecode kan de versiewaarde onderzoeken die is gekoppeld aan het huidige orchestratie-exemplaar en de uitvoering hierop aanpassen.

  • Achterwaartse compatibiliteit: Werkers met nieuwere orchestrator-versies kunnen doorgaan met het uitvoeren van orchestration-instanties die zijn gemaakt door oudere orchestrator-versies.

  • Forward Protection: De runtime voorkomt automatisch dat werknemers die oudere orchestratorversies uitvoeren, orchestrations uitvoeren die zijn gestart door nieuwere orchestratorversies.

Important

Orchestratie versiebeheer is momenteel beschikbaar als openbare voorlopige versie.

Vereiste voorwaarden

Voordat u orchestratieversies gebruikt, zorg ervoor dat u de vereiste pakketversies voor uw programmeertaal hebt.

Als u een non-.NET taal (JavaScript, Python, PowerShell of Java) met extensiebundels gebruikt, moet uw functie-app verwijzen naar extensiebundel versie 4.26.0 of hoger. Configureer het extensionBundle bereik in host.json zodat de minimale versie ten minste 4.26.0 is, bijvoorbeeld:

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

Zie de configuratiedocumentatie voor uitbreidingsbundels voor meer informatie over het kiezen en bijwerken van bundelversies.

Gebruik Microsoft.Azure.Functions.Worker.Extensions.DurableTask versie 1.5.0 of hoger.

Basaal gebruik

De meest voorkomende gebruikssituatie voor orchestratieversiebeheer is wanneer u belangrijke wijzigingen moet aanbrengen in de orchestrator logica terwijl bestaande orkestratie-instanties actief blijven met hun oorspronkelijke versie. U hoeft alleen maar de defaultVersion in uw host.json bij te werken en uw orchestratorcode te wijzigen om de orchestratieversie te controleren en uitvoering vervolgens vertakkingen dienovereenkomstig. Laten we de vereiste stappen doorlopen.

Note

Het gedrag dat in deze sectie wordt beschreven, is gericht op de meest voorkomende situaties. Dit is wat de standaardconfiguratie biedt. Het kan echter indien nodig worden gewijzigd (zie Geavanceerd gebruik voor meer informatie).

Stap 1: defaultVersion-configuratie

Als u de standaardversie voor uw indelingen wilt configureren, moet u de defaultVersion instelling in het host.json bestand in uw Azure Functions-project toevoegen of bijwerken:

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

De versietekenreeks kan elke indeling volgen die past bij uw versiebeheerstrategie:

  • Versiebeheer met meerdere onderdelen: "1.0.0", "2.1.0"
  • Eenvoudige nummering: "1", "2"
  • Op datum gebaseerd: "2025-01-01"
  • Aangepaste indeling: "v1.0-release"

Nadat u defaultVersion hebt ingesteld, worden alle nieuwe orkestratie-exemplaren permanent gekoppeld aan die versie.

Regels voor versievergelijking

Wanneer de Strict of CurrentOrOlder strategie is geselecteerd (bekijk Versiekoppeling), vergelijkt de runtime de versie van het orkestratie-exemplaar met de defaultVersion waarde van de workerrol met behulp van de volgende regels:

  • Lege of nulwaarden worden als gelijk beschouwd.
  • Een lege of null-versie wordt beschouwd als ouder dan een gedefinieerde versie.
  • Als beide versies kunnen worden geparseerd als System.Version, wordt de CompareTo methode gebruikt.
  • Anders wordt een niet-hoofdlettergevoelige tekenreeksvergelijking uitgevoerd.

Stap 2: Orchestrator-functielogica

Als u versiebewuste logica in uw orchestratorfunctie wilt implementeren, kunt u de contextparameter gebruiken die aan de orchestrator is doorgegeven voor toegang tot de versie van het huidige orchestration-exemplaar, zodat u de orchestratorlogica kunt vertakken op basis van de versie.

Important

Bij het implementeren van versiebewuste logica is het van cruciaal belang om de exacte orchestratorlogica voor oudere versies te behouden. Wijzigingen in de volgorde, volgorde of handtekening van activiteitenaanroepen voor bestaande versies kunnen deterministische herhaling verbreken en ervoor zorgen dat in-flight-indelingen mislukken of onjuiste resultaten opleveren. De oude versiecodepaden moeten ongewijzigd blijven zodra ze zijn geïmplementeerd.

[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
        ...
    }
    ...
}

Note

De context.Version eigenschap is alleen-lezen en weerspiegelt de versie die permanent was gekoppeld aan de orchestratie-instantiatie toen deze werd gemaakt. U kunt deze waarde niet wijzigen tijdens de uitvoering van de orkestratie. Als u een versie wilt opgeven via andere methoden dan host.json, kunt u dit doen wanneer u een orchestrationexemplaar start met de orchestration-client-API's (zie Nieuwe indelingen en subindelingen starten met specifieke versies).

Tip

Als u net begint met het gebruik van orchestratieversiebeheer en u al lopende orkestraties hebt die zijn gemaakt voordat u een defaultVersionhebt opgegeven, kunt u nu nog steeds de defaultVersion instelling toevoegen aan uw host.json. Voor alle eerder gemaakte indelingen retourneert context.Versionnull (of een equivalente taalafhankelijke waarde), zodat u de orchestratorlogica kunt structuren om zowel de verouderde (null-versie) als de nieuwe versie-indelingen dienovereenkomstig te verwerken. Hier volgen de taalafhankelijke waarden om te controleren voor de legacy case:

  • C#: context.Version == null of context.Version is null
  • JavaScript: context.df.version == null
  • Python: context.version is None
  • PowerShell: $null -eq $Context.Version
  • Java: context.getVersion() == null Houd er ook rekening mee dat het specificeren van "defaultVersion": null in host.json gelijk staat aan het helemaal niet specificeren.

Tip

Afhankelijk van uw situatie kunt u de voorkeur geven aan vertakkingen op verschillende niveaus. U kunt een lokale wijziging aanbrengen, precies waar deze wijziging is vereist, zoals in het voorbeeld wordt weergegeven. U kunt ook op een hoger niveau vertakken, zelfs op het volledige orchestrator-implementatieniveau, waarbij enige codeduplicatie wordt geïntroduceerd, maar de uitvoeringsstroom duidelijk kan blijven. Het is aan u om de methode te kiezen die het beste past bij uw scenario en coderingsstijl.

Wat gebeurt er na de implementatie?

Dit is wat u kunt verwachten wanneer u de bijgewerkte orchestratorfunctie implementeert met de nieuwe versielogica:

  • Co-existentie van werkrollen: werkrollen die de nieuwe orchestratorfunctiecode bevatten, worden gestart, terwijl sommige werkrollen met de oude code mogelijk nog actief zijn.

  • Versietoewijzing voor nieuwe instanties: Alle nieuwe orkestraties en sub-orkestraties die door de nieuwe werkprocessen zijn gemaakt, krijgen de versie van defaultVersion toegewezen.

  • Nieuwe werkerscompatibiliteit: Nieuwe werkers kunnen zowel de nieuw aangemaakte orkestraties als de reeds bestaande orkestraties verwerken, omdat de wijzigingen die in stap 2 van de vorige sectie zijn doorgevoerd, via versiebewuste vertakkingslogica compatibiliteit met eerdere versies verzekeren.

  • Beperkingen voor oude werkers: Oude werkers mogen alleen de orchestraties verwerken met een versie die gelijk is aan of lager dan de versie die in hun eigen defaultVersion versie is opgegeven. Dit komt omdat ze naar verwachting geen orchestratorcode hebben die compatibel is met nieuwere versies. Deze beperking voorkomt uitvoeringsfouten en onverwacht gedrag.

Note

Orkestratieversiebeheer heeft geen invloed op de levenscyclus van processen. Het Azure Functions-platform beheert het inrichten en buiten gebruik stellen van computing-resources op basis van reguliere regels, afhankelijk van hostinginstellingen.

Voorbeeld: Een activiteit in de reeks vervangen

In dit voorbeeld ziet u hoe u één activiteit door een andere activiteit vervangt in het midden van een reeks met behulp van orchestratieversiebeheer.

Versie 1.0

host.json configuratie:

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

Orchestratorfunctie:

[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";
}

Versie 2.0 met kortingsverwerking

host.json configuratie:

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

Orchestratorfunctie:

using DurableTask.Core.Settings;

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

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

    if (VersioningSettings.CompareVersions(context.Version, "1.0") <= 0)
    {
        // Preserve original logic for existing instances
        await context.CallActivityAsync("ProcessPayment", orderId);
    }
    else // a higher version (including 2.0)
    {
        // New logic with discount processing (replaces payment processing)
        await context.CallActivityAsync("ApplyDiscount", orderId);
        await context.CallActivityAsync("ProcessPaymentWithDiscount", orderId);
    }
    
    await context.CallActivityAsync("ShipOrder", orderId);

    return "Order processed successfully";
}

Geavanceerd gebruik

Voor geavanceerdere versiebeheerscenario's kunt u andere instellingen configureren om te bepalen hoe de runtime versieovereenkomsten en niet-overeenkomende verwerkt.

Tip

Gebruik de standaardconfiguratie (CurrentOrOlder met Reject) voor de meeste scenario's om veilige rolling implementaties mogelijk te maken, terwijl de orkestratiestatus behouden blijft tijdens versieovergangen. We raden u aan om alleen door te gaan met de geavanceerde configuratie als u specifieke vereisten hebt die niet kunnen worden voldaan aan het standaardgedrag.

Versieafstemming

De versionMatchStrategy instelling bepaalt hoe de runtime orchestratieversies overeenkomt bij het laden van orchestratorfuncties. Het bepaalt welke orkestratie-instanties een worker kan verwerken op basis van versiecompatibiliteit.

Configuration

{
  "extensions": {
    "durableTask": {
      "defaultVersion": "<version>",
      "versionMatchStrategy": "CurrentOrOlder"
    }
  }
}

Beschikbare strategieën

  • None (niet aanbevolen): Orchestratieversie volledig negeren. Alle ontvangen werkzaamheden worden verwerkt, ongeacht de versie. Met deze strategie wordt versiecontrole in feite uitgeschakeld en kan elke werknemer elk orchestration-exemplaar verwerken.

  • Strict: Alleen taken van orchestraties verwerken met precies dezelfde versie als opgegeven door defaultVersion in de werkrol host.json. Deze strategie biedt het hoogste niveau van versie-isolatie, maar vereist zorgvuldige implementatiecoördinatie om verweesde orkestraties te voorkomen. De gevolgen van niet-overeenkomende versies worden beschreven in de sectie Over niet-overeenkomende versies .

  • CurrentOrOlder (standaard): Procestaken van orkestraties die een versie hebben kleiner dan of gelijk aan de versie gespecificeerd door defaultVersion in de werkrol host.json. Deze strategie maakt achterwaartse compatibiliteit mogelijk, waardoor nieuwere werknemers indelingen kunnen verwerken die zijn gestart door oudere orchestratorversies, terwijl oudere werknemers voorkomen dat nieuwere indelingen worden verwerkt. De gevolgen van niet-overeenkomende versies worden beschreven in de sectie Over niet-overeenkomende versies .

Afhandeling van versie-mismatch

De versionFailureStrategy instelling bepaalt wat er gebeurt wanneer een versie van een orchestratie-instantie niet overeenkomt met de huidige defaultVersion versie.

Configuration:

{
  "extensions": {
    "durableTask": {
      "defaultVersion": "<version>",
      "versionFailureStrategy": "Reject"
    }
  }
}

Beschikbare strategieën:

  • Reject (standaard): De orkestratie niet verwerken. De orkestratie-instantie blijft in de huidige status en kan later opnieuw worden uitgevoerd wanneer er een compatibele werkrol beschikbaar komt. Deze strategie is de veiligste optie omdat de orkestratiestatus behouden blijft.

  • Fail: Mislukt de indeling. Deze strategie beëindigt de orkestratie-instantie onmiddellijk met een fouttoestand, wat geschikt kan zijn in scenario's waarin niet-overeenkomende versies duiden op ernstige uitrolproblemen.

Nieuwe orkestraties en sub-orkestraties starten met specifieke versies

Standaard worden alle nieuwe orkestratie-exemplaren gemaakt met de huidige defaultVersion die in uw host.json configuratie is opgegeven. Mogelijk hebt u echter scenario's waarin u orkestraties met een specifieke versie moet maken, zelfs als deze verschilt van de huidige standaardversie.

Wanneer moet u specifieke versies gebruiken:

  • Geleidelijke migratie: u wilt ook na het implementeren van een nieuwere versie, blijven werken met orkestraties van een oudere versie.
  • Testscenario's: Je moet het gedrag van specifieke versies testen in de productieomgeving.
  • Terugdraaisituaties: u moet tijdelijk terugkeren naar het maken van exemplaren met een eerdere versie.
  • Versiespecifieke werkstromen: voor verschillende bedrijfsprocessen zijn verschillende indelingsversies vereist.

U kunt de standaardversie overschrijven door een specifieke versiewaarde op te geven bij het maken van nieuwe orchestration-exemplaren met behulp van de orchestration-client-API's. Hiermee kunt u nauwkeurig bepalen welke versie elke nieuwe orchestration-instantie gebruikt.

[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);

    // ...
}

U kunt ook suborkestraties starten met specifieke versies vanuit een orkestratiefunctie:

[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);
    
    // ...
}

Verouderde codepaden verwijderen

Na verloop van tijd kunt u verouderde codepaden uit uw orchestratorfuncties verwijderen om het onderhoud te vereenvoudigen en de technische schulden te verminderen. Het verwijderen van code moet echter zorgvuldig worden uitgevoerd om te voorkomen dat bestaande orchestratie-instanties worden verstoord.

Wanneer het veilig is om verouderde code te verwijderen:

  • Alle orchestratie-instanties met de oude versie zijn afgesloten (geslaagd, mislukt of beëindigd)
  • Er worden geen nieuwe orkestratie-instanties gemaakt met de oude versie.
  • U hebt gecontroleerd door middel van monitoring of queries dat er geen exemplaren actief zijn met de verouderde versie.
  • Er is voldoende tijd verstreken sinds de oude versie voor het laatst is geïmplementeerd (rekening houdend met uw vereisten voor bedrijfscontinuïteit)

Aanbevolen procedures voor verwijdering:

  • Actieve exemplaren bewaken: gebruik de Durable Functions-beheer-API's om query's uit te voeren op exemplaren met behulp van specifieke versies.
  • Bewaarbeleid instellen: Geef aan hoe lang u compatibiliteit met eerdere versies voor elke versie wilt behouden.
  • Incrementeel verwijderen: Overweeg om één versie tegelijk te verwijderen in plaats van meerdere versies tegelijk.
  • Documentverwijdering: behoud duidelijke records van wanneer versies zijn verwijderd en waarom.

Warning

Het verwijderen van verouderde codepaden terwijl indelingsexemplaren nog steeds deze versies uitvoeren, kunnen deterministische herhalingsfouten of onverwacht gedrag veroorzaken. Controleer altijd of er geen exemplaren de verouderde versie gebruiken voordat u de code verwijdert.

Beste praktijken

Versiebeheer

  • Gebruik versiebeheer met meerdere onderdelen: Gebruik een consistent versiebeheerschema zoals major.minor.patch.
  • Wijzigingen die fouten veroorzaken in documenten: documenteer duidelijk welke wijzigingen een nieuwe versie vereisen.
  • Levenscyclus van de versie plannen: bepalen wanneer verouderde codepaden moeten worden verwijderd.

Codeorganisatie

  • Afzonderlijke versielogica: gebruik duidelijke vertakkingen of afzonderlijke methoden voor verschillende versies.
  • Determinisme behouden: voorkom dat bestaande versielogica wordt gewijzigd zodra deze is geïmplementeerd. Als wijzigingen absoluut noodzakelijk zijn (zoals kritieke foutoplossingen), moet u ervoor zorgen dat ze deterministisch gedrag behouden en de volgorde van bewerkingen niet wijzigen of verwachten dat de nieuwere orchestratorversies mislukken bij het verwerken van oudere indelingen.
  • Test grondig: Test alle versiepaden, met name tijdens overgangen.

Bewaking en waarneembaarheid

  • Informatie over logboekversies: neem de versie op in uw logboekregistratie voor eenvoudigere foutopsporing.
  • Versiedistributie bewaken: bijhouden welke versies actief worden uitgevoerd.
  • Waarschuwingen instellen: Controleren op eventuele versiegerelateerde fouten.

Troubleshooting

Algemene problemen

  • Probleem: Indelingsexemplaren die zijn gemaakt met versie 1.0 mislukken na het implementeren van versie 2.0

    • Oplossing: Zorg ervoor dat het codepad van versie 1.0 in uw orchestrator precies hetzelfde blijft. Wijzigingen in de uitvoeringsreeks kunnen deterministische herhaling verbreken.
  • Probleem: werkers met oudere orchestratorversies kunnen geen nieuwe orchestrationstaken uitvoeren

    • Oplossing: dit is verwacht gedrag. De runtime voorkomt opzettelijk dat oudere werknemers orchestrations met nieuwere versies uitvoeren om de veiligheid te behouden. Zorg ervoor dat alle werkers worden bijgewerkt naar de nieuwste orchestrator versie en dat hun defaultVersion instellingen in host.json dienovereenkomstig worden bijgewerkt. U kunt dit gedrag indien nodig wijzigen met behulp van de geavanceerde configuratieopties (zie Geavanceerd gebruik voor meer informatie).
  • Probleem: versie-informatie is niet beschikbaar in orchestrator (context.Version of context.getVersion() is null, ongeacht de defaultVersion instelling)

    • Oplossing: Controleer de sectie Vereisten om te verzekeren dat uw omgeving aan alle eisen voor orchestratieversiebeheer voldoet.
  • Probleem: Orchestraties van een nieuwere versie verlopen zeer langzaam of zijn volledig vastgelopen

    • Oplossing: Het probleem kan verschillende hoofdoorzaken hebben:
      1. Onvoldoende nieuwere arbeiders: zorg ervoor dat een voldoende aantal arbeiders met een gelijke of hogere versie in defaultVersion geïmplementeerd en actief zijn om de nieuwere orchestraties te verwerken.
      2. Indelingsrouteringsinterferentie van oudere werknemers: Oude werknemers kunnen het indelingsrouteringsmechanisme verstoren, waardoor het moeilijker wordt voor nieuwe werknemers om indelingen op te halen voor verwerking. Dit kan vooral merkbaar zijn bij het gebruik van bepaalde opslagproviders (Azure Storage of MSSQL). Normaal gesproken zorgt het Azure Functions-platform ervoor dat oude werknemers kort na een implementatie worden verwijderd, dus eventuele vertraging is doorgaans niet significant. Als u echter een configuratie gebruikt waarmee u de levenscyclus van oudere werknemers kunt beheren, moet u ervoor zorgen dat de oudere werknemers uiteindelijk worden afgesloten. U kunt ook de Durable Task Scheduler gebruiken, omdat het een verbeterd routeringsmechanisme biedt dat minder gevoelig is voor dit probleem.

Volgende stappen