Vincoli di codice della funzione di Orchestrator
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.UtcNow
o 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);
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.
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.Run
mai , Task.Delay
e 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 SynchronizationContext
della 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
, WaitForExternalEvent
e 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.
Per altre informazioni su come Durable Task Framework esegue le funzioni dell'agente di orchestrazione, vedere il codice sorgente di Durable Task in GitHub. In particolare, vedere TaskOrchestrationExecutor.cs e TaskOrchestrationContext.cs.