Eviga orkestreringar

Evig orkestrering är orkestreringsfunktioner som körs på obestämd tid genom att regelbundet återställa sin egen historik med hjälp av API:et continue-as-new . De är användbara för aggregatörer, periodiska bakgrundsjobb och alla Durable Functions-scenarion som kräver en oändlig loop utan obegränsad historiktillväxt.

Utan continue-as-newskulle en orkestrerare som loopar för alltid ackumulera orkestreringshistorik med varje schemalagd uppgift, vilket så småningom orsakar prestandaproblem och överdriven minnesanvändning. Det eviga orkestreringsmönstret löser detta genom att återställa historiken för varje iteration.

Anmärkning

Kodexempel för evig orkestrering är tillgängliga för C#, JavaScript, Python och Java. PowerShell stöder inte continue-as-new.

I den här artikeln:

Evig orkestrering är orkestreringar som körs på obestämd tid genom att regelbundet återställa sin egen historik med hjälp av API:et continue-as-new . De är användbara för aggregatorer, periodiska bakgrundsjobb, och alla scenarion som kräver en oändlig loop utan obegränsad historiktillväxt.

Utan continue-as-newskulle en orkestrering som loopar för alltid ackumulera historik med varje schemalagd uppgift, vilket så småningom orsakar prestandaproblem och överdriven minnesanvändning. Det eviga orkestreringsmönstret löser detta genom att återställa historiken för varje iteration.

Viktigt!

PowerShell Durable Task SDK är för närvarande inte tillgängligt.

I den här artikeln:

Hur "continue-as-new" fungerar

I stället för att använda oändliga loopar återställer orkestreringsfunktionerna sitt tillstånd genom att anropa continue-as-new metoden för orkestreringsutlösarbindningen. Den här metoden tar en JSON-serialiserbar parameter som blir nya indata för nästa orchestrator-funktionsgenerering.

När du anropar continue-as-newstartar orkestreringsinstansen om sig själv med det nya indatavärdet. Samma instans-ID behålls, men orkestreringsfunktionens historik återställs.

I stället för att använda oändliga loopar återställer orkestreringarna sitt tillstånd genom att anropa continue-as-new metoden i orkestreringskontexten. Den här metoden tar en JSON-serialiserbar parameter som blir nya indata för nästa orkestreringsgenerering.

När du anropar continue-as-newstartar orkestreringsinstansen om sig själv med det nya indatavärdet. Samma instans-ID behålls, men orkestreringens historik återställs.

Överväganden för evig orkestrering

Tänk på följande när du använder continue-as-new metoden i en orkestrering:

  • När en orchestrator-funktion återställs med hjälp continue-as-new av metoden behåller Durable Task Framework samma instans-ID men skapar och använder ett nytt körnings-ID internt framöver. Det här körnings-ID:t exponeras inte externt, men det är användbart när du felsöker orkestreringskörning.

  • När ett ohanterat undantag inträffar under körningen går orkestreringen in i ett misslyckat tillstånd och körningen avslutas. Ett anrop till continue-as-new från ett finally block startar inte om orkestreringen efter ett undantagsfel.

  • Resultaten av ofullständiga uppgifter kastas bort när en orkestrering anropar continue-as-new. Om en timer till exempel är schemalagd och sedan continue-as-new anropas innan timern utlöses ignoreras timerhändelsen.

  • Du kan valfritt bevara obearbetade externa händelser över continue-as-new omstarter. I C# ContinueAsNew bevarar obehandlade händelser som standard. I Java bevarar continueAsNew också händelser som standard. I Python bevarar continue_as_new inte händelser om inte save_events=True. I JavaScript continueAsNew kräver en saveEvents parameter (true eller false) för att styra det här beteendet.

Tänk på följande när du använder continue-as-new metoden i en orkestrering:

  • När en orkestrering återställs med hjälp continue-as-new av metoden behåller Durable Task SDK:erna samma instans-ID men skapar och använder ett nytt körnings-ID internt framöver. Det här körnings-ID:t exponeras inte externt, men det kan vara användbart när du felsöker orkestreringskörning.

  • När ett ohanterat undantag inträffar under körningen går orkestreringen in i ett misslyckat tillstånd och körningen avslutas. Ett anrop till continue-as-new från ett finally block startar inte om orkestreringen efter ett ohejdat undantag.

  • Resultaten av ofullständiga uppgifter kastas bort när en orkestrering anropar continue-as-new. Om en timer till exempel är schemalagd och sedan continue-as-new anropas innan timern utlöses ignoreras timerhändelsen.

  • Du kan valfritt bevara obearbetade externa händelser över continue-as-new omstarter. I .NET och Java bevarar continue-as-new obearbetade händelser som standard. I Python bevarar continue_as_new inte händelser om inte save_events=True. I JavaScript continueAsNew kräver en saveEvents parameter (true eller false) för att styra det här beteendet. I samtliga fall levereras obearbetade händelser när orkestreringen nästa gång anropar waitForExternalEvent eller wait_for_external_event.

Exempel på periodiskt arbete

Ett vanligt användningsfall för ständiga orkestreringar är periodiskt bakgrundsarbete, till exempel underhållsarbete.

Varför inte använda en timerutlösare? En CRON-baserad timerutlösare körs vid fasta tidpunkter oavsett om den tidigare körningen har slutförts. En ständig orkestrering väntar på att arbetet ska slutföras innan nästa iteration schemaläggs, så exekveringar överlappar aldrig.

Approach Schema (1 timmes intervall, 30 min jobb) Risk för överlappning
Timerutlösare (CRON) 1:00, 2:00, 3:00 Ja – om jobbet överskrider intervallet
Evig orkestration 1:00, 2:30, 4:00 Nej – nästa körning väntar på slutförande
[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;
    }
}

Starta en evig orkestrering

Använd metoden start-new eller schedule-new durable client för att starta en evig orkestrering, precis som andra orkestreringsfunktioner. Om du bara vill se till att en instans körs i taget använder du ett fast instans-ID. Mer information finns i Singleton-orkestreringar.

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

Använd schedule-new-klientmetoden för att starta en evig orkestrering, precis som vilken annan orkestrering som helst. Om du bara vill se till att en instans körs i taget använder du ett fast instans-ID. Mer information finns i Singleton-orkestreringar.

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

Avsluta en evig orkestrering

Om en orkestreringsfunktion så småningom behöver slutföras ska du inte anropa continue-as-new och låta funktionen avslutas.

Om en orchestrator-funktion finns i en oändlig loop och måste stoppas använder du terminate-API i orkestreringsklientbindningen för att stoppa den.

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

Mer information finns i Instanshantering.

Om en orkestrering så småningom behöver slutföras ska du inte anropa continue-as-new och låta orkestreringen avslutas.

Om en orkestrering finns i en oändlig loop och måste stoppas använder du avsluta API:et på den varaktiga aktivitetsklienten för att stoppa den.

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

Nästa steg