Eeuwige orkestraties

Eeuwige indelingen zijn orchestratorfuncties die voor onbepaalde tijd worden uitgevoerd door hun eigen geschiedenis periodiek opnieuw in te stellen met behulp van de continue-as-new API. Ze zijn handig voor aggregators, periodieke achtergrondtaken en elk Durable Functions scenario dat een oneindige lus vereist zonder niet-gebonden geschiedenisgroei.

Zonder continue-as-new zou een orchestrator die in een lus blijft draaien, met elke geplande taak de orchestratiegeschiedenis ophopen, waardoor uiteindelijk prestatieproblemen en overmatig geheugengebruik ontstaan. Het eeuwige orkestratiepatroon lost dit op door de geschiedenis bij elke iteratie opnieuw in te stellen.

Opmerking

Er zijn eeuwige indelingscodevoorbeelden beschikbaar voor C#, JavaScript, Python en Java. PowerShell biedt geen ondersteuning voor continue-as-new.

In dit artikel:

Eeuwige orkestraties zijn orkestraties die onbepaalde tijd draaien door periodiek hun geschiedenis opnieuw in te stellen via de continue-as-new API. Ze zijn handig voor aggregators, periodieke achtergrondtaken en elk scenario waarvoor een oneindige lus zonder niet-gebonden geschiedenisgroei is vereist.

Zonder continue-as-new, zou een orkestratie die eindeloos blijft draaien geschiedenis opbouwen met elke geplande taak, wat uiteindelijk leidt tot prestatieproblemen en overmatig geheugengebruik. Het eeuwig orchestratiepatroon lost dit op door de geschiedenis bij elke iteratie opnieuw in te stellen.

Belangrijk

Momenteel is de Durable Task SDK van PowerShell niet beschikbaar.

In dit artikel:

Hoe continue-as-new werkt

In plaats van oneindige lussen te gebruiken, stellen orchestratorfuncties hun status opnieuw in door de continue-as-new methode van de orchestration-triggerbinding aan te roepen. Deze methode gebruikt een JSON-serialiseerbare parameter die de nieuwe invoer wordt voor de volgende orchestratorfunctiegeneratie.

Wanneer u continue-as-new aanroept, wordt het orchestratie-exemplaar opnieuw opgestart met de nieuwe invoerwaarde. Dezelfde instance-ID wordt bewaard, maar de geschiedenis van de orchestratorfunctie wordt gereset.

In plaats van oneindige lussen te gebruiken, wordt de status van orchestrations opnieuw ingesteld door de continue-as-new methode aan te roepen in de orchestratiecontext. Deze methode gebruikt een JSON-serialiseerbare parameter die de nieuwe invoer wordt voor de volgende orchestratiegeneratie.

Wanneer u continue-as-new aanroept, wordt het orchestratie-exemplaar opnieuw opgestart met de nieuwe invoerwaarde. Dezelfde exemplaar-id wordt bewaard, maar de geschiedenis van de orkestratie wordt opnieuw gestart.

Overwegingen voor permanente orkestratie

Houd rekening met deze overwegingen bij het gebruik van de continue-as-new methode in een orkestratie:

  • Wanneer een orchestratorfunctie opnieuw wordt ingesteld met behulp van de continue-as-new methode, behoudt het Durable Task Framework dezelfde exemplaar-id, maar maakt en gebruikt intern een nieuwe uitvoerings-id . Deze uitvoerings-id wordt niet extern weergegeven, maar is handig bij het opsporen van fouten in de orkestratie-uitvoering.

  • Wanneer er een niet-verwerkte uitzondering optreedt tijdens de uitvoering, gaat de orkestratie naar een gefaalde status en wordt de uitvoering beëindigd. Een aanroep van continue-as-new vanuit een finally blok start de orkestratie niet opnieuw na een niet-onderschepte uitzondering.

  • De resultaten van onvoltooide taken worden genegeerd wanneer een orkestratie aanroept continue-as-new. Als een timer bijvoorbeeld is gepland en vervolgens continue-as-new wordt aangeroepen voordat de timer wordt geactiveerd, wordt de timergebeurtenis verwijderd.

  • U kunt eventueel niet-verwerkte externe gebeurtenissen behouden tijdens continue-as-new opnieuw opstarten. In C# ContinueAsNew blijven niet-verwerkte gebeurtenissen standaard behouden. In Java behoudt continueAsNew ook standaard gebeurtenissen. In Python worden continue_as_new gebeurtenissen niet behouden tenzij save_events=True. In JavaScript continueAsNew is een saveEvents parameter (true of false) vereist om dit gedrag te beheren.

Houd rekening met deze overwegingen bij het gebruik van de continue-as-new methode in een orkestratie:

  • Wanneer een orchestratie opnieuw wordt ingesteld met behulp van de continue-as-new methode, behouden de Durable Task SDK's dezelfde instance-ID, maar maken en gebruiken ze intern een nieuwe uitvoerings-ID. Deze uitvoerings-id wordt niet extern weergegeven, maar kan nuttig zijn bij het debuggen van de orchestratie-uitvoering.

  • Wanneer er een niet-verwerkte uitzondering optreedt tijdens de uitvoering, gaat de orkestratie naar een gefaalde status en wordt de uitvoering beëindigd. Een aanroep van continue-as-new vanuit een finally-blok start de orkestratie na een niet opgevangen uitzondering niet opnieuw op.

  • De resultaten van onvoltooide taken worden genegeerd wanneer een orkestratie aanroept continue-as-new. Als een timer bijvoorbeeld is gepland en vervolgens continue-as-new wordt aangeroepen voordat de timer wordt geactiveerd, wordt de timergebeurtenis verwijderd.

  • U kunt eventueel niet-verwerkte externe gebeurtenissen behouden tijdens continue-as-new opnieuw opstarten. In .NET en Java behoudt continue-as-new standaard niet-verwerkte gebeurtenissen. In Python worden continue_as_new gebeurtenissen niet behouden tenzij save_events=True. In JavaScript continueAsNew is een saveEvents parameter (true of false) vereist om dit gedrag te beheren. In alle gevallen worden niet-verwerkte gebeurtenissen geleverd wanneer de orchestratie de volgende keer waitForExternalEvent of wait_for_external_event aanroept.

Voorbeeld van periodiek werk

Een veelvoorkomende use case voor eeuwige orchestraties is periodiek achtergrondwerk, zoals opschoningstaken.

Waarom niet een timertrigger gebruiken? Een timertrigger op basis van CRON wordt op vaste tijden uitgevoerd, ongeacht of de vorige uitvoering is voltooid. Een eeuwige orkestratie wacht tot het werk is voltooid voordat de volgende iteratie wordt ingepland, zodat iteraties nooit overlappen.

Approach Schema (interval van 1 uur, taakduur van 30 minuten) Overlappingsrisico
Timer trigger (CRON) 1:00, 2:00, 3:00 Ja, als de taak het interval overschrijdt
Eeuwige orkestratie 1:00, 2:30, 4:00 Nee — volgende uitvoering wacht op voltooiing
[FunctionName("Periodic_Cleanup_Loop")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    await context.CallActivityAsync("DoCleanup", null);

    // sleep for one hour between cleanups
    DateTime nextCleanup = context.CurrentUtcDateTime.AddHours(1);
    await context.CreateTimer(nextCleanup, CancellationToken.None);

    context.ContinueAsNew(null);
}
public class PeriodicCleanupLoop : TaskOrchestrator<object?, object?>
{
    public override async Task<object?> RunAsync(TaskOrchestrationContext context, object? input)
    {
        await context.CallActivityAsync("DoCleanup");

        // sleep for one hour between cleanups
        await context.CreateTimer(TimeSpan.FromHours(1), CancellationToken.None);

        context.ContinueAsNew(null);
        return null;
    }
}

Een eeuwige orkestratie starten

Gebruik de start-nieuw of planning-nieuw duurzame clientmethode om een eeuwige orkestratie te starten, net als elke andere orkestratiefunctie. Gebruik een vaste exemplaar-id om ervoor te zorgen dat slechts één exemplaar tegelijk wordt uitgevoerd. Zie Singleton-orkestraties voor meer informatie.

[FunctionName("Trigger_Eternal_Orchestration")]
public static async Task<HttpResponseMessage> OrchestrationTrigger(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage request,
    [DurableClient] IDurableOrchestrationClient client)
{
    string instanceId = "StaticId";

    await client.StartNewAsync("Periodic_Cleanup_Loop", instanceId); 
    return client.CreateCheckStatusResponse(request, instanceId);
}

Gebruik de schedule-new clientmethode om een eeuwige orchestratie te starten, net als elke andere orchestratie. Gebruik een vaste exemplaar-id om ervoor te zorgen dat slechts één exemplaar tegelijk wordt uitgevoerd. Zie Singleton-orkestraties voor meer informatie.

string instanceId = "StaticId";
await client.ScheduleNewOrchestrationInstanceAsync(
    "PeriodicCleanupLoop",
    null,
    new StartOrchestrationOptions { InstanceId = instanceId });

Uit een eeuwige orkestratie stappen

Als een orchestratorfunctie uiteindelijk moet worden voltooid, roep de functie dan niet aan met continue-as-new en laat de functie afsluiten.

Als een orchestratorfunctie zich in een oneindige lus bevindt en moet worden gestopt, gebruikt u de beëindigings-API van de orchestration-clientbinding om deze te stoppen.

await client.TerminateAsync(instanceId, "Cleanup no longer needed");

Zie Exemplaarbeheer voor meer informatie.

Als een orkestratie uiteindelijk moet worden voltooid, roep dan continue-as-new niet aan en laat de orkestratie beëindigen.

Als een orkestratie zich in een oneindige lus bevindt en moet worden gestopt, gebruikt u de terminate-API op de duurzame taakclient om deze te stoppen.

await client.TerminateInstanceAsync(instanceId, "Cleanup no longer needed");

Volgende stappen