Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Versiebeheer in Durable Functions is essentieel omdat functies onvermijdelijk worden toegevoegd, verwijderd en gewijzigd gedurende de levensduur van een toepassing. Durable Functions kunt u functies koppelen op manieren die eerder niet mogelijk waren, en deze keten is van invloed op de manier waarop u versiebeheer verwerkt.
Dit artikel helpt je:
- Bepaal of uw codewijziging een belangrijke wijziging is.
- Kies de juiste risicobeperkingsstrategie om veilig te implementeren.
Snelle strategievergelijking
Als u al weet dat uw wijziging problemen veroorzaakt, gebruikt u deze tabel om een mitigatiestrategie te kiezen.
| Strategie | Het beste voor | Details |
|---|---|---|
| Orkestratieversiebeheer (aanbevolen) | De meeste toepassingen met belangrijke wijzigingen. Ingebouwde runtime-functie werkt met elke back-end voor opslag. | Ga naar de sectie |
| Parallelle implementaties | Apps die geen indelingsversiebeheer kunnen gebruiken of die volledige isolatie nodig hebben via afzonderlijke taakhubs of opslagaccounts. | Ga naar de sectie |
| Alle in-flight-exemplaren stoppen | Prototypen en lokale ontwikkeling waarbij het verlies van in-flight orkestraties acceptabel is. | Ga naar de sectie |
Aanbeveling
Als u op zoek bent naar de ingebouwde functie voor orchestratieversiebeheer die automatische versie-isolatie op runtimeniveau biedt, raadpleegt u Orchestratieversiebeheer.
Belangrijk
Controleer voordat u implementeert of uw wijziging een belangrijke wijziging is:
- Hebt u de naam, het invoertype of het uitvoertype van een activiteit of entiteitsfunctie gewijzigd?
- Hebt u aanroepen aan activiteiten, subindelingen, timers of externe gebeurtenissen in orchestratorcode toegevoegd, verwijderd of opnieuw gerangschikt?
- Hebt u de naam van een functie gewijzigd of verwijderd die in-flight orkestraties mogelijk nog steeds aanroepen?
Als u op een van deze vragen ja hebt geantwoord, gebruik dan een van de onderstaande mitigatiestrategieën om mislukkingen bij het uitvoeren van orkestraties te voorkomen.
Typen brekende wijzigingen
Er zijn verschillende voorbeelden van ingrijpende wijzigingen. In dit artikel worden de meest voorkomende typen besproken. Het belangrijkste thema achter al deze thema's is dat wijzigingen in functiecode van invloed zijn op zowel nieuwe als bestaande functie-indelingen.
Wijzigingen in de functiehandtekening van activiteiten of entiteiten
Een handtekeningwijziging verwijst naar een wijziging in de naam, invoer of uitvoer van een functie. Als u dit soort wijzigingen aanbrengt in een activiteit of entiteitsfunctie, kan deze elke orchestratorfunctie verbreken die ervan afhankelijk is. Dit gedrag geldt met name voor typeveilige talen. Als u de orchestrator-functie bijwerkt om deze wijziging aan te passen, kunt u bestaande exemplaren in flight breken.
Denk bijvoorbeeld aan de volgende orchestratorfunctie.
[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
bool result = await context.CallActivityAsync<bool>("Foo");
await context.CallActivityAsync("Bar", result);
}
Deze functie neemt het resultaat van Foo en geeft deze door aan Bar. Stel dat u de retourwaarde van Foo moet wijzigen van een Booleaanse waarde in een tekenreeks om een grotere verscheidenheid aan resultaatwaarden te ondersteunen. Het resultaat ziet er als volgt uit:
[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
string result = await context.CallActivityAsync<string>("Foo");
await context.CallActivityAsync("Bar", result);
}
Deze wijziging werkt prima voor alle nieuwe exemplaren van de orchestratorfunctie, maar kan eventuele in-flight-exemplaren breken. Denk bijvoorbeeld aan de situatie waarin een orchestration-exemplaar een functie aanroept met de naam Foo, een Booleaanse waarde terugkrijgt en vervolgens controlepunten weergeeft. Als de wijziging van de handtekening op dit moment wordt geïmplementeerd, mislukt het controlepuntexemplaar onmiddellijk wanneer het wordt hervat en de aanroep Foo opnieuw wordt afgespeeld. Deze fout treedt op omdat het resultaat in de geschiedenistabel een Booleaanse waarde is, maar de nieuwe code probeert deze te deserialiseren in een tekenreekswaarde, wat resulteert in onverwacht gedrag of zelfs een runtime-uitzondering voor typeveilige talen.
Dit voorbeeld is een van de vele manieren waarop een wijziging van een functie-signature bestaande exemplaren kan beïnvloeden. Als een orchestrator in het algemeen de manier moet wijzigen waarop een functie wordt aangeroepen, is de wijziging waarschijnlijk problematisch.
Wijzigingen in de logica van de orchestrator
De andere klasse versiebeheerproblemen komt door het wijzigen van de orchestrator-functiecode op een manier die het uitvoeringspad voor in-flight-exemplaren wijzigt.
Houd rekening met de volgende orchestratorfunctie:
[FunctionName("FooBar")]
public static Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
bool result = await context.CallActivityAsync<bool>("Foo");
await context.CallActivityAsync("Bar", result);
}
Stel nu dat u een nieuwe functie-aanroep wilt toevoegen tussen de twee bestaande functie-aanroepen.
[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);
}
Met deze wijziging wordt een nieuwe functie-aanroep toegevoegd aan SendNotification tussen Foo en Bar. Er zijn geen handtekeningwijzigingen. Het probleem treedt op wanneer een bestaande instantie wordt hervat van de aanroep naar Bar. Als tijdens het opnieuw afspelen de oorspronkelijke aanroep naar Footrue heeft geretourneerd, roept de orchestrator tijdens de replay SendNotification aan, wat zich niet in de uitvoeringsgeschiedenis bevindt. De runtime detecteert deze inconsistentie en genereert een niet-deterministische orkestratiefout omdat er een aanroep naar SendNotification werd aangetroffen terwijl een aanroep naar Bar werd verwacht. Hetzelfde type probleem kan optreden bij het toevoegen van API-aanroepen aan andere duurzame bewerkingen, zoals het maken van duurzame timers, het wachten op externe gebeurtenissen of het aanroepen van subindelingen.
Risicobeperkingsstrategieën
Waarschuwing
Het implementeren van belangrijke wijzigingen zonder een risicobeperkingsstrategie (de 'niets-doen' benadering) kan ertoe leiden dat orkestraties mislukken met niet-deterministische orkestratiefouten, voor onbepaalde tijd vastlopen in een Running-status, of laag-niveau runtimefouten activeren die de prestaties verminderen. Gebruik altijd een van de volgende strategieën bij het implementeren van belangrijke wijzigingen.
Orchestratieversiebeheer (aanbevolen)
In tegenstelling tot de andere strategieën in deze sectie is orkestratieversiebeheer een ingebouwde runtime-functie die automatische versie-isolatie biedt. U hoeft geen afzonderlijke implementaties, taakhubs of opslagaccounts te beheren. In plaats daarvan houdt de runtime zelf versie-informatie bij en zorgt ervoor dat orchestratie-instanties worden verwerkt door compatibele werkers.
Met orchestratie-versiebeheer:
- Elke orchestratie-instantie krijgt bij de aanmaak een versie die er permanent aan is gekoppeld.
- Orchestrator-functies kunnen de uitvoering van hun versie en vertakking dienovereenkomstig onderzoeken, waardoor oude en nieuwe codepaden in dezelfde codebasis behouden blijven.
- Werknemers die nieuwere versies van de orchestratorfunctie gebruiken, kunnen doorgaan met het uitvoeren van orkestratie-instanties die door oudere versies zijn gecreëerd.
- De runtime voorkomt dat werkers die oudere versies van orchestratorfuncties gebruiken, orkestraties van nieuwere versies uitvoeren.
Deze benadering vereist minimale configuratie (een versiestring en een optionele overeenkomstenstrategie) en is compatibel met elke opslagprovider. Het is de aanbevolen strategie voor toepassingen die belangrijke wijzigingen moeten ondersteunen terwijl implementaties zonder downtime worden gehandhaafd.
Zie Orchestration-versiebeheer voor gedetailleerde configuratie- en implementatierichtlijnen.
Alle in-flight-instances stoppen
Een andere optie is om alle in-flight exemplaren te stoppen. Als u de standaardprovider Azure Storage gebruikt voor Durable Functions, stopt u alle exemplaren door de inhoud van de interne control-queue en workitem-queue wachtrijen te wissen. U kunt ook de functie-app stoppen, deze wachtrijen verwijderen en de app opnieuw starten. De wachtrijen worden automatisch opnieuw gemaakt zodra de app opnieuw wordt opgestart. De vorige orkestratie-instanties blijven mogelijk voor onbepaalde tijd in de "Actief"-status, maar ze vullen uw logboeken niet met foutmeldingen of veroorzaken geen schade aan uw app. Deze aanpak is ideaal voor snelle prototypeontwikkeling, inclusief lokale ontwikkeling.
Waarschuwing
Deze benadering vereist directe toegang tot de onderliggende opslagbronnen en is niet geschikt voor alle opslagproviders die worden ondersteund door Durable Functions.
Implementaties naast elkaar
De meest fail-proof manier om ervoor te zorgen dat belangrijke wijzigingen veilig worden geïmplementeerd, is door ze naast uw oudere versies te implementeren. U kunt een van de volgende technieken gebruiken:
- Ander opslagaccount: Implementeer alle updates als een nieuwe functie-app met een ander opslagaccount. Hiermee wordt de status van de nieuwe versie volledig geïsoleerd van de oude versie.
- Verschillende taakhub: Implementeer een nieuwe kopie van de functie-app met hetzelfde opslagaccount, maar met een bijgewerkte taakhubnaam . Met deze methode worden nieuwe opslagartefacten gemaakt voor de nieuwe versie, terwijl de oude versie de bestaande artefacten blijft gebruiken.
Wanneer u zij-aan-zij implementaties uitvoert in Azure, kunt u deploymentslots gebruiken om beide versies tegelijkertijd uit te voeren, waarbij slechts één als de actieve productie slot fungeert. Wanneer u klaar bent om de nieuwe orkestratielogica beschikbaar te maken, wisselt u de nieuwe versie in het productieslot.
Opmerking
Deze richtlijnen maken gebruik van Azure Storage-specifieke termen, maar zijn over het algemeen van toepassing op alle ondersteunde Durable Functions-opslagproviders.
Opmerking
Implementatieslotwisselingen werken het beste met HTTP- en webhooktriggers. Voor niet-HTTP-triggers, zoals wachtrijen of Event Hubs, moet de triggerdefinitie worden afgeleid van een app-instelling die wordt bijgewerkt als onderdeel van de wisselbewerking.