Durable Functions è un'estensione di Funzioni di Azure che consente di compilare app con stato. È possibile usare una funzione di orchestrazione per orchestrare l'esecuzione di altre funzioni durevoli all'interno di un'app per le funzioni. Le funzioni dell'agente di orchestrazione sono con stato, affidabile e potenzialmente a esecuzione prolungata.
Vincoli del codice dell'agente di orchestrazione
Le funzioni di orchestrazione usano l'origine eventi per garantire l'esecuzione affidabile e per mantenere lo stato della variabile locale. Il comportamento di riproduzione del codice dell'agente di orchestrazione crea vincoli sul tipo di codice che è possibile scrivere in una funzione dell'agente di orchestrazione. Ad esempio, le funzioni dell'agente di orchestrazione devono essere deterministiche: una funzione dell'agente di orchestrazione verrà riprodotta più volte e deve produrre lo stesso risultato ogni volta.
Uso delle API deterministiche
Questa sezione fornisce alcune linee guida semplici che consentono di assicurarsi che il codice sia deterministico.
Le funzioni dell'agente di orchestrazione possono chiamare qualsiasi API nelle relative lingue di destinazione. Tuttavia, è importante che le funzioni dell'agente di orchestrazione chiamino solo API deterministiche.
Un'API deterministica è un'API che restituisce sempre lo stesso valore dato lo stesso input, indipendentemente dalla frequenza o dalla frequenza con cui viene chiamata.
Le sezioni seguenti forniscono indicazioni sulle API e sui modelli che è consigliabile evitare perché non sono deterministici. Queste restrizioni si applicano solo alle funzioni dell'agente di orchestrazione. Altri tipi di funzione non hanno tali restrizioni.
Nota
Di seguito sono descritti diversi tipi di vincoli di codice. Questo elenco non è purtroppo completo e alcuni casi d'uso potrebbero non essere trattati. La cosa più importante da considerare quando si scrive il codice dell'agente di orchestrazione è se un'API usata è deterministica. Dopo aver pensato in questo modo, è facile capire quali API sono sicure da usare e quali non sono senza bisogno di fare riferimento a questo elenco documentato.
Date e ore
Le API che restituiscono la data o l'ora correnti non sono deterministiche e non devono mai essere usate nelle funzioni dell'agente di orchestrazione. Ciò avviee perché ogni riproduzione della funzione dell'agente di orchestrazione produrrà un valore diverso. È invece consigliabile usare l'API equivalente Durable Functions per ottenere la data o l'ora correnti, che rimane coerente tra le riproduzioni.
Non usare DateTime.Now, DateTime.UtcNowo API equivalenti per ottenere l'ora corrente. Anche le classi, ad Stopwatch esempio, devono essere evitate. Per le funzioni di orchestrazione in-process .NET, usare la proprietà per ottenere l'ora IDurableOrchestrationContext.CurrentUtcDateTime corrente. Per le funzioni dell'agente di orchestrazione isolato .NET, usare la TaskOrchestrationContext.CurrentDateTimeUtc proprietà per ottenere l'ora corrente.
DateTime startTime = context.CurrentUtcDateTime;
// do some work
TimeSpan totalTime = context.CurrentUtcDateTime.Subtract(startTime);
Non usare API come new Date() o Date.now() per ottenere la data e l'ora correnti. Usare invece DurableOrchestrationContext.currentUtcDateTime.
// create a timer that expires 2 minutes from now
const expiration = moment.utc(context.df.currentUtcDateTime).add(2, "m");
const timeoutTask = context.df.createTimer(expiration.toDate());
Non usare datetime.now(), gmtime()o API simili per ottenere l'ora corrente. Usare invece DurableOrchestrationContext.current_utc_datetime.
# create a timer that expires 2 minutes from now
expiration = context.current_utc_datetime + timedelta(seconds=120)
timeout_task = context.create_timer(expiration)
Non usare cmdlet come Get-Date o API .NET come [System.DateTime]::Now per ottenere l'ora corrente. Usare invece $Context.CurrentUtcDateTime.
$expiryTime = $Context.Input.ExpiryTime
while ($Context.CurrentUtcDateTime -lt $expiryTime) {
# do work
}
Non usare API come LocalDateTime.now() o Instant.now() per ottenere la data e l'ora correnti. Usare invece TaskOrchestrationContext.getCurrentInstant().
Instant startTime = ctx.getCurrentInstant();
// do some work
Duration totalTime = Duration.between(startTime, ctx.getCurrentInstant());
GUID e UUID
Le API che restituiscono un GUID casuale o UUID non sono univoche perché il valore generato è diverso per ogni riproduzione. A seconda della lingua usata, è possibile che sia disponibile un'API predefinita per la generazione di GUID deterministici o UUID. In caso contrario, usare una funzione di attività per restituire un GUID o un UUID generato in modo casuale.
Non usare API come Guid.NewGuid() generare GUID casuali. Usare invece l'API dell'oggetto contesto per generare un GUID casuale sicuro per la riproduzione dell'agente NewGuid() di orchestrazione.
Guid randomGuid = context.NewGuid();
Nota
I GUID generati con LE API del contesto di orchestrazione sono Tipi 5 UUID.
Non usare il modulo o la uuidcrypto.randomUUID() funzione per generare UUID casuali. Usare invece il metodo predefinito newGuid() dell'oggetto context per generare un GUID casuale sicuro per la riproduzione dell'agente di orchestrazione.
const randomGuid = context.df.newGuid();
Nota
Gli UUID generati con LE API del contesto di orchestrazione sono Tipi 5 UUID.
Non usare il uuid modulo per generare UUID casuali. Usare invece il metodo predefinito new_guid() dell'oggetto context per generare un UUID casuale sicuro per la riproduzione dell'agente di orchestrazione.
randomGuid = context.new_guid()
Nota
Gli UUID generati con LE API del contesto di orchestrazione sono Tipi 5 UUID.
Non usare cmdlet come New-Guid o API .NET come [System.Guid]::NewGuid() direttamente nelle funzioni dell'agente di orchestrazione. Generare invece GUID casuali nelle funzioni di attività e restituirli alle funzioni dell'agente di orchestrazione.
Non usare i metodi o simili per generare nuovi UUID direttamente nelle funzioni dell'agente java.util.UUID.randomUUID() di orchestrazione. Generare invece uUID casuali nelle funzioni di attività e restituirli alle funzioni dell'agente di orchestrazione.
Numeri casuali
Usare una funzione di attività per restituire numeri casuali a una funzione dell'agente di orchestrazione. I valori restituiti delle funzioni di attività sono sempre sicuri per la riproduzione perché vengono salvati nella cronologia dell'orchestrazione.
In alternativa, un generatore di numeri casuali con un valore di inizializzazione fisso può essere usato direttamente in una funzione di agente di orchestrazione. Questo approccio è sicuro finché la stessa sequenza di numeri viene generata per ogni riproduzione dell'orchestrazione.
Associazioni
Una funzione dell'agente di orchestrazione non deve usare associazioni, incluse anche le associazioni client di orchestrazione e client di entità . Usare sempre associazioni di input e output dall'interno di una funzione client o attività. Ciò è importante perché le funzioni dell'agente di orchestrazione possono essere riprodotte più volte, causando l'I/O non deterministico e duplicato con sistemi esterni.
Variabili statiche
Evitare l'uso di variabili statiche nelle funzioni dell'agente di orchestrazione perché i valori possono cambiare nel tempo, causando un comportamento di runtime non deterministico. Usare invece costanti o limitare l'uso di variabili statiche alle funzioni di attività.
Nota
Anche all'esterno delle funzioni dell'agente di orchestrazione, l'uso di variabili statiche in Funzioni di Azure può essere problematico per un'ampia gamma di motivi, poiché non esiste alcuna garanzia che lo stato statico persisterà tra più esecuzioni di funzioni. Le variabili statiche devono essere evitate tranne in casi d'uso molto specifici, ad esempio la memorizzazione nella cache in memoria ottimale nelle funzioni di attività o entità.
Variabili di ambiente
Non usare le variabili di ambiente nelle funzioni dell'agente di orchestrazione. I valori possono cambiare nel tempo, causando un comportamento di runtime non deterministico. Se una funzione di orchestrazione richiede la configurazione definita in una variabile di ambiente, è necessario passare il valore di configurazione nella funzione dell'agente di orchestrazione come input o come valore restituito di una funzione di attività.
Rete e HTTP
Usare le funzioni attività per effettuare chiamate di rete in uscita. Se è necessario effettuare una chiamata HTTP dalla funzione dell'agente di orchestrazione, è anche possibile usare le API HTTP durevoli.
API di blocco dei thread
I blocchi delle API come "sospensione" possono causare problemi di prestazioni e scalabilità per le funzioni dell'agente di orchestrazione e devono essere evitati. Nel piano di utilizzo Funzioni di Azure possono anche comportare addebiti per l'esecuzione non necessari. Usare le alternative per bloccare le API quando sono disponibili. Ad esempio, usare timer durevoli per creare ritardi sicuri per la riproduzione e non contare sul tempo di esecuzione di una funzione dell'agente di orchestrazione.
API asincrone
Il codice dell'agente di orchestrazione non deve mai avviare alcuna operazione asincrona, ad eccezione di quelli definiti dall'oggetto contesto del trigger di orchestrazione. Ad esempio, non usare Task.Runmai , Task.Delaye HttpClient.SendAsync in .NET o setTimeout in setInterval JavaScript. Una funzione dell'agente di orchestrazione deve pianificare solo il lavoro asincrono usando le API di Durable SDK, ad esempio le funzioni di pianificazione delle attività. Qualsiasi altro tipo di chiamate asincrone deve essere eseguito all'interno delle funzioni di attività.
Funzioni JavaScript asincrone
Dichiarare sempre funzioni dell'agente di orchestrazione JavaScript come funzioni del generatore sincrono. Non è necessario dichiarare le funzioni dell'agente di orchestrazione JavaScript come async perché il runtime Node.js non garantisce che le funzioni asincrone siano deterministiche.
Coroutine Python
Non è necessario dichiarare le funzioni dell'agente di orchestrazione Python come coroutine. In altre parole, non dichiarare mai le funzioni dell'agente di orchestrazione Python con la parola chiave perché la async semantica di coroutine non è allineata al modello di riproduzione Durable Functions. È sempre necessario dichiarare le funzioni dell'agente di orchestrazione Python come generatori, vale a dire che è necessario che l'API context usi yield invece di await.
API di threading .NET
Durable Task Framework esegue il codice dell'agente di orchestrazione in un singolo thread e non può interagire con altri thread. L'esecuzione di continuazioni asincrone in un thread del pool di lavoro che l'esecuzione di un'orchestrazione può comportare l'esecuzione non deterministica o i deadlock. Per questo motivo, le funzioni dell'agente di orchestrazione dovrebbero quasi mai usare le API di threading. Ad esempio, non usare ConfigureAwait(continueOnCapturedContext: false) mai in una funzione dell'agente di orchestrazione. In questo modo si garantisce che le continuazioni delle attività vengano eseguite nell'originale SynchronizationContextdella funzione dell'agente di orchestrazione.
Nota
Durable Task Framework tenta di rilevare l'uso accidentale di thread non di orchestrazione nelle funzioni dell'agente di orchestrazione. Se rileva una violazione, il framework genera un'eccezione NonDeterministicOrchestrationException . Tuttavia, questo comportamento di rilevamento non intercetta tutte le violazioni e non deve dipendere da esso.
Controllo delle versioni
Un'orchestrazione durevole può essere eseguita continuamente per giorni, mesi, anni o persino eternamente. Qualsiasi aggiornamento del codice apportato a Durable Functions app che influiscono sulle orchestrazioni non completate potrebbe interrompere il comportamento di riproduzione delle orchestrazioni. Ecco perché è importante pianificare attentamente quando si apportano aggiornamenti al codice. Per una descrizione più dettagliata della versione del codice, vedere l'articolo sul controllo delle versioni.
Attività permanenti
Nota
Questa sezione descrive i dettagli di implementazione interna del framework di attività permanenti. È possibile usare funzioni durevoli senza conoscere queste informazioni. che vengono date al solo scopo di comprendere il comportamento di riesecuzione.
Le attività che possono attendere in modo sicuro nelle funzioni dell'agente di orchestrazione vengono occasionalmente definite attività durevoli. Durable Task Framework crea e gestisce queste attività. Gli esempi sono le attività restituite da CallActivityAsync, WaitForExternalEvente CreateTimer nelle funzioni dell'agente di orchestrazione .NET.
Queste attività durevoli vengono gestite internamente da un elenco di TaskCompletionSource oggetti in .NET. Durante la riproduzione, queste attività vengono create come parte dell'esecuzione del codice dell'agente di orchestrazione. Il dispatcher enumera gli eventi della cronologia corrispondenti.
Le attività vengono eseguite in modo sincrono usando un singolo thread fino a quando non viene riprodotta tutta la cronologia. Le attività durevoli che non vengono completate entro la fine della riproduzione della cronologia hanno azioni appropriate eseguite. Ad esempio, un messaggio potrebbe essere accodato per chiamare una funzione di attività.
Questa sezione descrive il comportamento di runtime per comprendere perché una funzione dell'agente di orchestrazione non può usare await o yield in un'attività non durevole. Esistono due motivi: il thread dispatcher non può attendere il completamento dell'attività e qualsiasi callback da tale attività potrebbe potenzialmente danneggiare lo stato di rilevamento della funzione dell'agente di orchestrazione. Alcuni controlli di runtime sono disponibili per consentire di rilevare queste violazioni.
Informazioni su come orchestrare un flusso di lavoro a esecuzione prolungata come un set di attività tramite funzioni Durable Functions scalabili e convenienti.