Orchestrazioni eterne

Le orchestrazioni eterne sono funzioni dell'agente di orchestrazione eseguite a tempo indeterminato reimpostando periodicamente la propria cronologia usando l'API continue-as-new . Sono utili per aggregatori, processi in background periodici e qualsiasi scenario Durable Functions che richiede un ciclo infinito senza che la cronologia cresca in modo incontrollato.

Senza continue-as-new, un orchestratore che cicla all'infinito accumulerebbe la cronologia di orchestrazione con ogni attività pianificata, che alla fine causa problemi di prestazioni e un uso eccessivo della memoria. Il modello di orchestrazione eterna risolve questo problema reimpostando la cronologia in ogni iterazione.

Annotazioni

Gli esempi di codice di orchestrazione eterna sono disponibili per C#, JavaScript, Python e Java. PowerShell non supporta continue-as-new.

Contenuto dell'articolo:

Le orchestrazioni eterne sono orchestrazioni eseguite a tempo indeterminato reimpostando periodicamente la propria cronologia usando l'API continue-as-new . Sono utili per aggregatori, processi in background periodici e qualsiasi scenario che richiede un ciclo di esecuzione infinito senza una crescita incontrollata della cronologia.

Senza continue-as-new, un'orchestrazione che si ripete indefinitamente accumulerebbe cronologia con ogni attività pianificata, causando inevitabilmente problemi di prestazioni e un uso eccessivo della memoria. Il modello di orchestrazione eterna risolve questo problema reimpostando la cronologia in ogni iterazione.

Importante

Attualmente, Durable Task SDK di PowerShell non è disponibile.

Contenuto dell'articolo:

Come funziona la funzione 'continue-as-new'

Anziché usare cicli infiniti, le funzioni di orchestrazione reimpostano il proprio stato chiamando il metodo continue-as-new dell'associazione del trigger di orchestrazione. Questo metodo accetta un parametro serializzabile JSON che diventa il nuovo input per la generazione della funzione dell'agente di orchestrazione successiva.

Quando si chiama continue-as-new, l'istanza di orchestrazione viene riavviata con il nuovo valore di input. Viene mantenuto lo stesso ID istanza, ma la cronologia della funzione dell'agente di orchestrazione viene ripristinata.

Anziché usare cicli infiniti, le orchestrazioni reimpostano lo stato chiamando il metodo nel continue-as-new contesto di orchestrazione. Questo metodo accetta un parametro serializzabile JSON che diventa il nuovo input per la generazione di orchestrazione successiva.

Quando si chiama continue-as-new, l'istanza di orchestrazione viene riavviata con il nuovo valore di input. Viene mantenuto lo stesso ID istanza, ma la cronologia dell'orchestrazione viene ripristinata.

Considerazioni sull'orchestrazione eterna

Tenere presenti queste considerazioni quando si usa il continue-as-new metodo in un'orchestrazione:

  • Quando una funzione di orchestratore viene reimpostata usando il metodo continue-as-new, Durable Task Framework mantiene lo stesso ID istanza, ma internamente crea e usa un nuovo ID di esecuzione da quel momento in avanti. L'ID esecuzione non è esposto esternamente, ma è utile per eseguire il debug dell'esecuzione dell'orchestrazione.

  • Quando si verifica un'eccezione non gestita durante l'esecuzione, l'orchestrazione entra in uno stato di errore e l'esecuzione termina. Una chiamata a continue-as-new da un finally blocco non riavvia l'orchestrazione dopo un'eccezione non rilevata.

  • I risultati di qualsiasi attività incompleta vengono eliminati quando un'orchestrazione chiama continue-as-new. Ad esempio, se viene pianificato un timer e quindi continue-as-new viene chiamato prima che venga attivato il timer, l'evento timer viene rimosso.

  • Facoltativamente, è possibile mantenere eventi esterni non elaborati tra continue-as-new riavvii. In C# ContinueAsNew mantiene gli eventi non elaborati per impostazione predefinita. In Java, anche continueAsNew mantiene gli eventi per impostazione predefinita. In Python, continue_as_new non mantiene gli eventi a meno che non save_events=True. In JavaScript, continueAsNew richiede un parametro saveEvents (true o false) per controllare questo comportamento.

Tenere presenti queste considerazioni quando si usa il continue-as-new metodo in un'orchestrazione:

  • Quando un'orchestrazione viene reimpostata usando il continue-as-new metodo, gli SDK di Durable Task mantengono lo stesso ID istanza, ma creano internamente e usano un nuovo ID di esecuzione d'ora in avanti. Questo ID di esecuzione non è esposto esternamente, ma può essere utile per il debug dell'esecuzione dell'orchestrazione.

  • Quando si verifica un'eccezione non gestita durante l'esecuzione, l'orchestrazione entra in uno stato di errore e l'esecuzione termina. Una chiamata da un blocco finally a continue-as-newnon riavvia l'orchestrazione dopo un'eccezione non rilevata.

  • I risultati di qualsiasi attività incompleta vengono eliminati quando un'orchestrazione chiama continue-as-new. Ad esempio, se viene pianificato un timer e quindi continue-as-new viene chiamato prima che venga attivato il timer, l'evento timer viene rimosso.

  • Facoltativamente, è possibile mantenere eventi esterni non elaborati tra continue-as-new riavvii. In .NET e Java, continue-as-new mantiene gli eventi non elaborati per impostazione predefinita. In Python, continue_as_new non mantiene gli eventi a meno che non save_events=True. In JavaScript, continueAsNew richiede un parametro saveEvents (true o false) per controllare questo comportamento. In tutti i casi, gli eventi non elaborati vengono recapitati quando l'orchestrazione chiama waitForExternalEvent o wait_for_external_event.

Esempio di lavoro periodico

Un caso d'uso comune per le orchestrazioni eterne è il lavoro in background periodico, ad esempio i compiti di pulizia.

Perché non usare un trigger del timer? Un trigger timer basato su CRON viene eseguito in momenti fissi indipendentemente dal fatto che l'esecuzione precedente sia stata completata. Un'orchestrazione eterna attende il completamento del lavoro prima di pianificare l'iterazione successiva, quindi le esecuzioni non si sovrappongono mai.

Avvicinarsi Pianificazione (intervallo di 1 ora, attività di 30 minuti) Rischio di sovrapposizione
Timer trigger (CRON) 1:00, 2:00, 3:00 Sì, se il lavoro supera l'intervallo
Orchestrazione eterna 1:00, 2:30, 4:00 No: l'esecuzione successiva attende il completamento
[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;
    }
}

Avvia un'orchestrazione eterna

Usare il metodo client permanente start-new o schedule-new per avviare un'orchestrazione eterna, proprio come qualsiasi altra funzione di orchestrazione. Per assicurarsi che venga eseguita una sola istanza alla volta, usare un ID istanza fissa. Per altre informazioni, vedere Orchestrazioni Singleton.

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

Usare il metodo client schedule-new per avviare un'orchestrazione continuativa, proprio come qualsiasi altra orchestrazione. Per assicurarsi che venga eseguita una sola istanza alla volta, usare un ID istanza fissa. Per altre informazioni, vedere Orchestrazioni Singleton.

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

Uscire da un'orchestrazione perenne

Se una funzione dell'orchestratore deve eventualmente completarsi, non chiamare continue-as-new e lascia che la funzione si concluda.

Se una funzione dell'agente di orchestrazione si trova in un ciclo infinito e deve essere arrestata, usare l'API terminatedell'associazione client di orchestrazione per arrestarla.

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

Per altre informazioni, vedere Gestione delle istanze.

Se un'orchestrazione deve essere completata, non chiamare continue-as-new e lasciare che l'orchestrazione termini.

Se un'orchestrazione si trova in un ciclo infinito e deve essere arrestata, usare l'API terminate nel client per attività durevoli per arrestarla.

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

Passaggi successivi