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.
Een duurzame indeling maakt gebruik van een orchestratorfunctie om de uitvoering van andere functies te coördineren in een betrouwbare, langlopende werkstroom die volledig in code is gedefinieerd. Orchestrator-functies hebben de volgende kenmerken:
- Ze definiëren werkstromen met behulp van procedurele code. Er zijn geen declaratieve schema's of ontwerpers nodig.
- Ze roepen andere functies synchroon en asynchroon aan. Je kunt output van aangeroepen functies opslaan naar lokale variabelen.
- Ze checkpointen automatisch de voortgang van de uitvoering wanneer de functie een
awaitOR-operatoryieldaanroept, zodat het proces de lokale status niet verliest wanneer het recyclet of de VM opnieuw opstart. - Ze ondersteunen langlopende processen. De totale levensduur van een orkestratie-instance kan seconden, dagen of maanden zijn, of u kunt het instance zo configureren dat het nooit eindigt.
Dit artikel bevat een overzicht van duurzame indelingen, waaronder indelingsidentiteit, gebeurtenisbronnen, uitvoeringsgeschiedenis en algemene werkstroompatronen, zoals subindelingen, duurzame timers en foutafhandeling.
Important
De ondersteuning wordt beëindigd voor het in-process model op 10 november 2026. We raden u ten zeerste aan uw apps te migreren naar het geïsoleerde werknemersmodel voor volledige ondersteuning.
Zie Durable Task programming model voor meer informatie over de typen functies die beschikbaar zijn in een Durable Functions-app.
Aanbeveling
Als je C# gebruikt met het .NET geïsoleerde workermodel, kun je orkestraties schrijven door ofwel een functie-gebaseerde benadering te gebruiken (statische methoden met [Function] attributen) of een klasse-gebaseerde aanpak (klassen die erven van TaskOrchestrator<TInput, TOutput>). De op klassen gebaseerde benadering vereist het brongeneratorpakket Microsoft.DurableTask.Generators en biedt sterk getypte aanroepen. Zie Brongeneratoren en op klassen gebaseerde syntaxis voor meer informatie. In de C#-codevoorbeelden in dit artikel worden beide benaderingen weergegeven.
De Durable Task SDK's bieden dezelfde orchestratormogelijkheden als Durable Functions voor het bouwen van betrouwbare, langlopende werkstromen met parallelle verwerking en gebeurtenisgestuurde coördinatie. In tegenstelling tot Durable Functions worden Durable Task SDK-indelingen uitgevoerd als zelfstandige toepassingen die worden ondersteund door de Durable Task Scheduler.
Orchestratie-identiteit
Elk exemplaar van een orchestratie heeft een exemplaar-id, ook bekend als een exemplaar-id. Standaard is elke exemplaar-id een automatisch gegenereerde GUID (Globally Unique Identifier). Je kunt echter elke door de gebruiker gegenereerde stringwaarde als instantie-ID gebruiken. Elke orkestratie-instantie-id moet uniek zijn binnen een taakhub.
De volgende regels zijn van toepassing op exemplaar-id's:
- Ze moeten tussen de 1 en 100 tekens zijn.
- Ze mogen niet beginnen met
@. - Ze mogen geen
/,\,#of?tekens bevatten. - Ze mogen geen besturingstekens bevatten.
Opmerking
Gebruik waar mogelijk automatisch gegenereerde exemplaar-id's. Gebruik door gebruikers gegenereerde instance ID's voor scenario's waarin er een één-op-één mapping is tussen een orchestratie-instantie en een externe, applicatiespecifieke entiteit, zoals een inkooporder of een document.
Opmerking
De daadwerkelijke afdwinging van regels voor tekenbeperking kan variëren, afhankelijk van de opslagprovider die door de app wordt gebruikt. Volg de voorgaande regels voor exemplaar-id's om ervoor te zorgen dat het juiste gedrag en de juiste compatibiliteit worden gegarandeerd.
De exemplaar-id van een orchestration is een vereiste parameter voor de meeste exemplaarbeheerbewerkingen. Exemplaar-id's zijn ook belangrijk voor diagnostische gegevens. U gebruikt deze bijvoorbeeld wanneer u in Application Insights door orchestratietraceringsgegevens zoekt voor probleemoplossing of voor analytische doeleinden. Sla daarom gegenereerde exemplaar-id's op een externe locatie op, zodat u er later eenvoudig naar kunt verwijzen, zoals een database of toepassingslogboeken.
De exemplaar-id van een orchestration is een vereiste parameter voor de meeste exemplaarbeheerbewerkingen. Exemplaar-id's zijn ook belangrijk voor diagnostische gegevens, dus sla gegenereerde exemplaar-id's op een externe locatie op waarmee u er later eenvoudig naar kunt verwijzen, zoals een database of toepassingslogboeken.
Reliability
Orchestrator-functies maken gebruik van het ontwerppatroon "event sourcing" om hun uitvoeringsstaat betrouwbaar bij te houden. In plaats van de huidige status van een orkestratie rechtstreeks op te slaan, maakt het Durable Task Framework gebruik van een alleen-toevoegopslag om de volledige reeks acties vast te leggen die door de functieorkestratie worden uitgevoerd. Een winkel met alleen toevoeggegevens heeft veel voordelen vergeleken met het dumpen van de volledige runtimestatus. Voordelen zijn verbeterde prestaties, schaalbaarheid en reactiesnelheid. U krijgt ook uiteindelijke consistentie voor transactionele gegevens, volledige audittrails en geschiedenis. De audittrails ondersteunen betrouwbare compenserende acties.
Het Durable Task Framework maakt op transparante wijze gebruik van event sourcing. Achter de schermen gebruikt een orchestratorfunctie een operator await in C# en een operator yield in JavaScript en Python. Deze operators geven de controle van de orchestratorthread terug aan de dispatcher van het Durable Task Framework. In Java levert het aanroepen van .await() op een taak de controle terug naar de dispatcher via een aangepast exemplaar van Throwable. De dispatcher voert vervolgens nieuwe acties door die door de orchestrator-functie naar de opslag worden gepland. Voorbeelden van acties zijn het aanroepen van een of meer child functies of het plannen van een duurzame timer. Met de transparante commit-actie wordt de uitvoeringsgeschiedenis van de orkestratie-instantie bijgewerkt door alle nieuwe gebeurtenissen toe te voegen aan de opslag, vergelijkbaar met een append-only logboek. Op dezelfde manier maakt de commitactie berichten in de opslag aan om het eigenlijke werk te plannen. Op dit moment kan de orchestratorfunctie uit het geheugen worden verwijderd.
Durable Functions maakt standaard gebruik van Azure Storage als runtimestatusopslag, maar andere opslagproviders worden ook ondersteund.
Wanneer een orkestratiefunctie meer werk krijgt (bijvoorbeeld een antwoordbericht wordt ontvangen of een duurzame timer verloopt), wordt de orchestrator geactiveerd en voert de gehele functie opnieuw uit vanaf het begin om de lokale status opnieuw op te bouwen. Als tijdens het opnieuw afspelen wordt geprobeerd een functie aan te roepen (of andere asynchrone werkzaamheden uit te voeren), raadpleegt het Durable Task Framework de uitvoeringsgeschiedenis van de huidige indeling. Als wordt gevonden dat de activiteit al is uitgevoerd en een resultaat heeft opgeleverd, wordt het resultaat van die functie opnieuw afgespeeld en blijft de orchestratorcode actief. De herhaling gaat door totdat de functiecode is voltooid of totdat er nieuwe asynchrone taken worden gepland.
Opmerking
Om het herhalingspatroon correct en betrouwbaar te laten werken, moet de orchestrator-functiecode deterministisch zijn. Niet-deterministische orchestratorcode kan leiden tot runtimefouten of ander onverwacht gedrag. Zie Orchestrator-functiecodebeperkingen voor meer informatie over codebeperkingen voor orchestratorfuncties.
Opmerking
Als een orchestratorfunctie logboekberichten verzendt, kan het gedrag voor opnieuw afspelen ertoe leiden dat dubbele logboekberichten worden verzonden. Als u wilt weten waarom dit gedrag optreedt en hoe u dit kunt omzeilen, raadpleegt u Logboekregistratie met replay-safe.
Orchestratiegeschiedenis
Het event-sourcing gedrag van het Durable Task Framework is nauw gekoppeld aan de orkestratiefunctiecode die u schrijft. Stel dat u een orchestratorfunctie voor activiteitenketens hebt, zoals in het volgende voorbeeld.
Geïsoleerd werkermodel
[Function("HelloCities")]
public static async Task<List<string>> Run(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));
// Return ["Hello Tokyo!", "Hello Seattle!", "Hello London!"].
return outputs;
}
Model op basis van klasse (geïsoleerde werkrol)
De op klassen gebaseerde benadering maakt gebruik van een brongenerator en vereist het NuGet-pakket Microsoft.DurableTask.Generators .
using Microsoft.DurableTask;
[DurableTask]
public class HelloCities : TaskOrchestrator<object?, List<string>>
{
public override async Task<List<string>> RunAsync(
TaskOrchestrationContext context, object? input)
{
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));
// Return ["Hello Tokyo!", "Hello Seattle!", "Hello London!"].
return outputs;
}
}
Model tijdens het proces
[FunctionName("HelloCities")]
public static async Task<List<string>> Run(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));
// Return ["Hello Tokyo!", "Hello Seattle!", "Hello London!"].
return outputs;
}
using Microsoft.DurableTask;
[DurableTask]
public class HelloCities : TaskOrchestrator<object?, List<string>>
{
public override async Task<List<string>> RunAsync(TaskOrchestrationContext context, object? input)
{
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));
return outputs;
}
}
Telkens wanneer je een activiteitsfunctie plant, slaat het Duurzame Taakraamwerk de uitvoeringstoestand van de functie op bij verschillende controlepunten. Bij elk controlepunt slaat het framework de status op in een duurzame opslagback-end. Deze status is de geschiedenis van de orkestratie.
Geschiedenistabel
Bij elk controlepunt voert het Duurzame Taakraamwerk de volgende acties uit:
- Slaat de uitvoeringsgeschiedenis op in duurzame opslag.
- Enqueues-berichten voor functies die de orchestrator wil aanroepen.
- Enqueues berichten voor de orchestrator zelf, zoals betrouwbare timerberichten.
Wanneer het checkpoint is voltooid, verwijdert het framework de orchestratorfunctie uit het geheugen totdat er weer werk voor de orchestratorfunctie is.
Opmerking
Azure Storage biedt geen transactionele garanties over dataconsistentie tussen tabelopslag en wachtrijen wanneer het data opslaat. Voor het afhandelen van fouten gebruikt de Durable Functions Azure Storage-provider eventuele consistentie patronen. Deze patronen helpen ervoor te zorgen dat er geen gegevens verloren gaan als er een crash of verlies van connectiviteit is in het midden van een controlepunt. Alternatieve opslagproviders, zoals de Durable Functions MSSQL-opslagprovider (Microsoft SQL Server, bieden mogelijk sterkere consistentiegaranties.
Zodra de functie die eerder is getoond, voltooid is, ziet de geschiedenis eruit zoals de gegevens in de volgende tabel in Table Storage. De vermeldingen worden afgekort voor illustratie.
| PartitionKey (InstanceId) | Type van evenement | Tijdstempel | Invoer | Naam | Resultaat | Status |
|---|---|---|---|---|---|---|
| eaee885b | UitvoeringGestart | 2021-05-05T18:45:28.852Z | nul | HelloCities | ||
| eaee885b | OrkestratorGestart | 2021-05-05T18:45:32.362Z | ||||
| eaee885b | TaakGepland | 2021-05-05T18:45:32.670Z | ZegHallo | |||
| eaee885b | OrchestratorCompleted | 2021-05-05T18:45:32.670Z | ||||
| eaee885b | TaakVoltooid | 2021-05-05T18:45:34.201Z | """"Hallo Tokio!""" | |||
| eaee885b | OrkestratorGestart | 2021-05-05T18:45:34.232Z | ||||
| eaee885b | TaakGepland | 2021-05-05T18:45:34.435Z | ZegHallo | |||
| eaee885b | OrchestratorCompleted | 2021-05-05T18:45:34.435Z | ||||
| eaee885b | TaakVoltooid | 2021-05-05T18:45:34.763Z | """Hallo Seattle!""" | |||
| eaee885b | OrkestratorGestart | 2021-05-05T18:45:34.857Z | ||||
| eaee885b | TaakGepland | 2021-05-05T18:45:34.857Z | ZegHallo | |||
| eaee885b | OrchestratorCompleted | 2021-05-05T18:45:34.857Z | ||||
| eaee885b | TaakVoltooid | 2021-05-05T18:45:34.919Z | """Hallo Londen!""" | |||
| eaee885b | OrkestratorGestart | 2021-05-05T18:45:35.032Z | ||||
| eaee885b | OrchestratorCompleted | 2021-05-05T18:45:35.044Z | ||||
| eaee885b | UitvoeringVoltooid | 2021-05-05T18:45:35.044Z | "[""Hallo Tokio!"",""Hallo Seattle!"",""Hallo Londen!""]" | Volbracht |
De tabelkolommen bevatten de volgende waarden:
- PartitionKey: De exemplaar-id van de orchestratie.
- EventType: het type gebeurtenis. Zie Durable Task Framework History Events voor gedetailleerde beschrijvingen van alle geschiedenisgebeurtenissen.
- Tijdstempel: de Coordinated Universal Time-tijdstempel van de geschiedenisgebeurtenis.
- Invoer: De JSON-indelingsinvoer van de functie.
- Naam: De naam van de aangeroepen functie.
- Resultaat: De uitvoer van de functie, met name de retourwaarde.
Waarschuwing
Deze tabel is handig als hulpprogramma voor foutopsporing, maar de indeling en inhoud kunnen veranderen naarmate de extensie Durable Functions zich ontwikkelt.
Telkens wanneer de functie wordt hervat nadat wordt gewacht totdat een taak is voltooid, voert het Durable Task Framework de orchestrator-functie opnieuw uit. Bij elke nieuwe uitvoering wordt de uitvoeringsgeschiedenis geraadpleegd om te bepalen of de huidige asynchrone taak is voltooid. Als in de uitvoeringsgeschiedenis wordt aangegeven dat de taak al is voltooid, wordt de uitvoer van die taak opnieuw afgespeeld en naar de volgende taak verplaatst. Dit proces wordt voortgezet totdat de volledige uitvoeringsgeschiedenis opnieuw wordt afgespeeld. Nadat de huidige uitvoeringsgeschiedenis opnieuw is afgespeeld, worden de lokale variabelen hersteld naar de vorige waarden.
Functies en patronen
In de volgende secties worden de functies en patronen van orchestratorfuncties beschreven.
Subindelingen in orchestratorfuncties
Orchestratorfuncties kunnen activiteitsfuncties aanroepen, maar ze kunnen ook andere orchestratorfuncties aanroepen. U kunt bijvoorbeeld een grotere orkestratie maken uit een bibliotheek met orchestratiefuncties. U kunt ook meerdere exemplaren van een orchestratorfunctie parallel uitvoeren.
Zie Suborkestraties in Durable Functions (Azure Functions) voor meer informatie en voorbeelden.
Duurzame timers
Orchestraties kunnen duurzame timers plannen om vertragingen te realiseren of time-out afhandeling in te stellen voor asynchrone acties. Gebruik duurzame timers in orchestratorfuncties in plaats van taaleigen sleep API's.
Zie Timers in Durable Functions (Azure Functions) voor meer informatie en voorbeelden.
Externe gebeurtenissen
Orchestrator-functies kunnen wachten op externe gebeurtenissen om een orkestratie-instance bij te werken. Deze Durable Functions-functie is vaak handig voor het verwerken van menselijke interacties of andere externe callbacks.
Zie Externe gebeurtenissen verwerken in Durable Functions (Azure Functions) voor meer informatie en voorbeelden.
Foutafhandeling
Orchestrator-functies kunnen gebruikmaken van de foutafhandelingsfuncties van de programmeertaal. Orkestratiecode ondersteunt bestaande patronen zoals try/catch.
Orchestrator-functies kunnen ook beleid voor opnieuw proberen toevoegen aan de activiteits- of suborchestratorfuncties die ze aanroepen. Als een activiteit of sub-orchestratorfunctie mislukt met een uitzondering, kan het opgegeven beleid voor opnieuw proberen de uitvoering automatisch vertragen en opnieuw proberen tot een opgegeven aantal keren.
Opmerking
Als er een niet-verwerkte uitzondering is in een orkestratiefunctie, wordt het orkestratie-exemplaar in een Failed staat voltooid. Je kunt een orkestratieinstantie niet opnieuw proberen nadat deze is mislukt.
Zie Fouten verwerken in Durable Functions (Azure Functions) voor meer informatie en voorbeelden.
Kritieke secties (Durable Functions 2.x)
Orchestratie-exemplaren zijn eendradig, dus racecondities zijn geen probleem binnen een orkestratie. Racevoorwaarden zijn echter mogelijk wanneer orkestraties communiceren met externe systemen. Om racecondities bij interactie met externe systemen te beperken, kunnen orchestratorfuncties kritieke secties definiëren door gebruik te maken van een lock. .NET en JavaScript ondersteunen kritieke secties.
In de volgende voorbeeldcode ziet u een orchestratorfunctie waarmee een kritieke sectie wordt gedefinieerd. Het betreden van het kritieke gedeelte vereist het doorgeven van één of meer referenties aan een duurzame entiteit, die de vergrendelingstoestand duurzaam beheert. Slechts één exemplaar van deze orchestratie kan de code in de kritieke sectie tegelijkertijd uitvoeren.
Gebruik de LockAsync methode om het kritieke gedeelte te betreden.
[FunctionName("Synchronize")]
public static async Task Synchronize(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var lockId = new EntityId("LockEntity", "MyLockIdentifier");
using (await context.LockAsync(lockId))
{
// Critical section. Only one orchestration can enter at a time.
}
}
Gebruik in .NET-geïsoleerde worker-orchestraties TaskOrchestrationContext.Entities.LockEntitiesAsync (zie .NET-geïsoleerde API-toewijzing).
De LockAsync methode verkrijgt de duurzame vergrendelingen en retourneert een IDisposable die de kritieke sectie beëindigt wanneer deze wordt verwijderd. Dit IDisposable resultaat kan samen met een using blok worden gebruikt om een syntactische weergave van de kritieke sectie op te halen. Wanneer een orchestratorfunctie een kritieke sectie invoert, kan slechts één exemplaar dat codeblok uitvoeren. Alle andere exemplaren die proberen de kritieke sectie in te voeren, worden geblokkeerd totdat het vorige exemplaar de kritieke sectie verlaat.
De kritieke sectiefunctie is ook handig voor het coördineren van wijzigingen in duurzame entiteiten. Zie Entiteitscoördinatie voor meer informatie over kritieke secties.
Opmerking
Kritieke secties zijn beschikbaar in Durable Functions 2.x voor .NET- en JavaScript-orkestraties. Voor .NET verschilt de API per model: in-process gebruikt IDurableOrchestrationContext.LockAsync, terwijl geïsoleerde gebruikt TaskOrchestrationContext.Entities.LockEntitiesAsync.
Aanroepen naar HTTP-eindpunten (Durable Functions 2.x)
Orchestratorfuncties kunnen geen I/O-operaties uitvoeren, zoals beschreven in de codebeperkingen van de Orchestrator-functie. Om deze beperking te omzeilen, wikkel je code die I/O-operaties moet uitvoeren in een activiteitsfunctie. Indelingen die communiceren met externe systemen gebruiken vaak activiteitsfuncties om HTTP-aanroepen uit te voeren en de resultaten terug te geven aan de indeling.
Om dit algemene patroon te stroomlijnen, kunnen orchestratorfuncties de CallHttpAsync methode gebruiken om RECHTSTREEKS HTTP-API's aan te roepen.
Geïsoleerd werkermodel
[Function("CheckSiteAvailable")]
public static async Task CheckSiteAvailable(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
Uri url = context.GetInput<Uri>();
// Make an HTTP GET request to the specified endpoint.
DurableHttpResponse response = await context.CallHttpAsync(
method: HttpMethod.Get,
uri: url,
content: null,
retryOptions: null);
if ((int)response.StatusCode == 400)
{
// Handle error codes.
}
}
Model tijdens het proces
[FunctionName("CheckSiteAvailable")]
public static async Task CheckSiteAvailable(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
Uri url = context.GetInput<Uri>();
// Make an HTTP GET request to the specified endpoint.
DurableHttpResponse response =
await context.CallHttpAsync(HttpMethod.Get, url);
if ((int)response.StatusCode == 400)
{
// Handle error codes.
}
}
Naast het ondersteunen van basisverzoek- en responspatronen, ondersteunt de methode automatische afhandeling van veelvoorkomende asynchrone HTTP 202-pollingpatronen. Het ondersteunt ook verificatie met externe services met behulp van beheerde identiteiten.
Zie HTTP-functies voor meer informatie en voor gedetailleerde voorbeelden.
Opmerking
Http-eindpunten rechtstreeks aanroepen vanuit orchestratorfuncties is beschikbaar in Durable Functions 2.0 en hoger.
Meerdere parameters doorgeven aan activiteitsfuncties
Je kunt niet meerdere parameters direct aan een activiteitsfunctie doorgeven. Geef in plaats daarvan een array van objecten of samengestelde objecten door.
Geïsoleerd werkermodel
Gebruik in .NET een serialiseerbare samengestelde type, zoals een record, om meerdere parameters door te geven.
public record CourseInfo(string Major, int UniversityYear);
[Function("GetCourseRecommendations")]
public static async Task<object> RunOrchestrator(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
int universityYear = context.GetInput<int>();
CourseInfo courseInfo = new("ComputerScience", universityYear);
object courseRecommendations = await context.CallActivityAsync<object>(
"CourseRecommendations", courseInfo);
return courseRecommendations;
}
Model tijdens het proces
Gebruik in .NET een serializeerbaar samengesteld type om meerdere parameters door te geven. In het volgende voorbeeld wordt een eenvoudige klasse gebruikt:
public class CourseInfo
{
public string Major { get; set; }
public int UniversityYear { get; set; }
}
[FunctionName("GetCourseRecommendations")]
public static async Task<object> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var input = new CourseInfo
{
Major = "ComputerScience",
UniversityYear = context.GetInput<int>()
};
object courseRecommendations = await context.CallActivityAsync<object>(
"CourseRecommendations",
input);
return courseRecommendations;
}
In .NET gebruik je recordtypes of tuples om meerdere parameters als één samengesteld object door te geven.
using Microsoft.DurableTask;
public record LocationInfo(string City, string State);
[DurableTask]
public class GetWeatherOrchestration : TaskOrchestrator<object?, string>
{
public override async Task<string> RunAsync(TaskOrchestrationContext context, object? input)
{
var location = new LocationInfo("Seattle", "WA");
string weather = await context.CallActivityAsync<string>("GetWeather", location);
return weather;
}
}