Durable Functions guida alla risoluzione dei problemi

Questo articolo illustra come risolvere gli scenari comuni nelle app Durable Functions. Trovare il sintomo nell'elenco seguente e seguire i passaggi collegati per diagnosticare e risolvere il problema.

Sintomi comuni

Per le query di diagnostica KQL che è possibile eseguire in Application Insights, vedere Esempi di query KQL per la diagnostica delle Durable Functions.

L'orchestrazione è bloccata nello stato di Pending

Quando si avvia un'orchestrazione, un messaggio "start" viene scritto in una coda interna gestita dall'estensione Durable e lo stato dell'orchestrazione è impostato su "In sospeso". Dopo che un'istanza dell'app disponibile riprende ed elabora correttamente il messaggio di orchestrazione, lo stato passa a "In esecuzione" (o a un altro stato non in sospeso).

Seguire questa procedura per risolvere i problemi relativi alle istanze di orchestrazione che rimangono bloccate per un tempo indefinito nello stato "In sospeso".

  1. Controllare le tracce di Durable Task Framework per la presenza di avvisi o errori per l'ID istanza di orchestrazione interessata. Usare la query Errori di traccia e avvisi in Application Insights per cercare gli errori correlati all'istanza.

  2. Controlla le code di Archiviazione di Azure per verificare se il "messaggio di avvio" dell'orchestrazione è ancora presente nella coda di controllo. Nel portale di Azure, vai al tuo account di archiviazione, seleziona Code e cerca le code con un prefisso control. Per informazioni sul funzionamento delle code di controllo, vedere la documentazione relativa alla coda di controllo del provider Archiviazione di Azure.

  3. Modificare la configurazione della piattaforma dell'app in 64 bit. L'avvio delle orchestrazioni a volte non riesce perché l'app esaurisce la memoria. Il passaggio a un processo a 64 bit consente all'app di allocare più memoria totale. Questa modifica si applica solo ai piani Basic, Standard, Premium e Elastic Premium del servizio app. I piani gratuito o a consumo non supportano processi a 64 bit.

Le orchestrazioni iniziano dopo un lungo ritardo

In genere, le orchestrazioni iniziano entro pochi secondi dopo la pianificazione. Tuttavia, l'avvio delle orchestrazioni potrebbe richiedere più tempo in determinati casi. Per risolvere i problemi relativi alle orchestrazioni che impiegano più di qualche secondo per iniziare l'esecuzione, seguire questi passaggi.

  1. Controllare se il ritardo corrisponde a una nota limitazione del provider di Archiviazione di Azure, come il ribilanciamento delle partizioni o gli intervalli di polling a tempo.

  2. Controllare le tracce del Durable Task Framework per individuare eventuali avvisi o errori relativi all'ID dell'istanza di orchestrazione interessata. Nell'ambito di Application Insights, usare la query errori di trace e avvisi per cercare gli errori correlati alla tua istanza.

L'orchestrazione è bloccata nello stato di Running

Se lo stato dell'orchestrazione mostra "Running" per più tempo del previsto o se sembra aver smesso di fare progressi, è probabile che l'orchestrazione sia in attesa di un'attività che non è stata completata. Ad esempio, potrebbe essere in attesa di un timer durevole, un compito, o un evento esterno. Se le attività pianificate sono state completate correttamente, ma l'orchestrazione non avanza ancora, potrebbe verificarsi un problema che impedisce di procedere al passaggio successivo. Le orchestrazioni in questo stato sono spesso chiamate "orchestrazioni bloccate".

Per risolvere i problemi relativi alle orchestrazioni bloccate, seguire questa procedura:

  1. Provare a riavviare l'app delle funzioni. Questo passaggio può essere utile se l'orchestrazione si blocca a causa di un bug temporaneo o di un deadlock nell'app o nel codice di estensione.

  2. Controllare le code di controllo dell'account di archiviazione di Azure per verificare se alcune code aumentano continuamente. Usare la query di messaggistica Archiviazione di Azure in Application Insights per identificare i problemi relativi alla rimozione della coda dei messaggi di orchestrazione. Se il problema interessa solo una singola coda di controllo, potrebbe indicare un problema in un'istanza specifica dell'app. In tal caso, aumentare o ridurre le risorse per spostarsi dall'istanza di macchina virtuale non funzionante potrebbe essere utile.

  3. Filtrare i risultati della query di messaggistica di Archiviazione di Azure in base al nome della coda come ID di partizione per individuare problemi correlati a quella specifica partizione della coda di controllo.

  4. Controllare la documentazione sul versionamento di Durable Functions. Le modifiche significative alle istanze di orchestrazione in esecuzione possono causare orchestrazioni bloccate.

Il completamento dell'orchestrazione richiede più tempo del previsto

L'elaborazione dei dati intensa, gli errori interni e le risorse di calcolo insufficienti possono causare l'esecuzione delle orchestrazioni più lente del normale. Per risolvere i problemi relativi alle orchestrazioni che richiedono più tempo del previsto, seguire questa procedura:

  1. Controllare le tracce di Durable Task Framework per la presenza di avvisi o errori per l'ID istanza di orchestrazione interessata. Usare la query Errori di traccia e avvisi in Application Insights per cercare gli errori correlati all'istanza.

  2. Se l'app usa il modello in-process .NET, è consigliabile abilitare sessioni estese. Le sessioni estese riducono al minimo i caricamenti della cronologia, che possono rallentare l'elaborazione.

  3. Verificare la presenza di colli di bottiglia in relazione a prestazioni e scalabilità. Un utilizzo elevato della CPU o un utilizzo elevato della memoria può causare ritardi. Per una guida dettagliata, vedere Prestazioni e scalabilità in Durable Functions.

Esempi di query KQL per la diagnostica delle Durable Functions

Risolvere i problemi scrivendo query personalizzate KQL nell'istanza di applicazione Azure Insights configurata per l'app Funzioni di Azure. Per le definizioni di colonna usate in queste query, vedere il riferimento alla colonna.

Archiviazione di Azure messaggistica

Quando si usa il provider di Archiviazione di Azure predefinito, tutto il comportamento Durable Functions è basato sui messaggi della coda Archiviazione di Azure e tutto lo stato correlato a un'orchestrazione viene archiviato nell'archiviazione tabelle e nell'archiviazione BLOB. Quando si abilita la traccia di Durable Task Framework, tutte le interazioni Archiviazione di Azure vengono registrate in Application Insights. Questi dati sono importanti per il debug di problemi di esecuzione e prestazioni.

A partire dalla versione 2.3.0 dell'estensione Durable Functions, è possibile pubblicare questi log di Durable Task Framework nell'istanza di Application Insights aggiornando la configurazione di registrazione nel file host.json. Per altre informazioni, vedere l'articolo Registrazione di Durable Task Framework.

La query seguente esamina le interazioni end-to-end Archiviazione di Azure per un'istanza di orchestrazione specifica. Modifica start e orchestrationInstanceID per filtrare in base all'intervallo di tempo e all'ID istanza.

let start = datetime(XXXX-XX-XXTXX:XX:XX); // edit this 
let orchestrationInstanceID = "XXXXXXX"; //edit this
traces  
| where timestamp > start and timestamp < start + 1h 
| where customDimensions.Category == "DurableTask.AzureStorage" 
| extend taskName = customDimensions["EventName"]
| extend eventType = customDimensions["prop__EventType"] 
| extend extendedSession = customDimensions["prop__IsExtendedSession"]
| extend account = customDimensions["prop__Account"] 
| extend details = customDimensions["prop__Details"] 
| extend instanceId = customDimensions["prop__InstanceId"] 
| extend messageId = customDimensions["prop__MessageId"] 
| extend executionId = customDimensions["prop__ExecutionId"] 
| extend age = customDimensions["prop__Age"] 
| extend latencyMs = customDimensions["prop__LatencyMs"] 
| extend dequeueCount = customDimensions["prop__DequeueCount"] 
| extend partitionId = customDimensions["prop__PartitionId"] 
| extend eventCount = customDimensions["prop__TotalEventCount"] 
| extend taskHub = customDimensions["prop__TaskHub"] 
| extend pid = customDimensions["ProcessId"]
| extend appName = cloud_RoleName
| extend newEvents = customDimensions["prop__NewEvents"]
| where instanceId == orchestrationInstanceID
| sort by timestamp asc
| project timestamp, appName, severityLevel, pid, taskName, eventType, message, details, messageId, partitionId, instanceId, executionId, age, latencyMs, dequeueCount, eventCount, newEvents, taskHub, account, extendedSession, sdkVersion

Errori di traccia e avvisi

La query seguente cerca errori e avvisi per una determinata istanza di orchestrazione. Specificare un valore per orchestrationInstanceID.

let orchestrationInstanceID = "XXXXXX"; // edit this
let start = datetime(XXXX-XX-XXTXX:XX:XX); 
traces  
| where timestamp > start and timestamp < start + 1h
| extend instanceId = iif(isnull(customDimensions["prop__InstanceId"] ) , customDimensions["prop__instanceId"], customDimensions["prop__InstanceId"] ) 
| extend logLevel = customDimensions["LogLevel"]
| extend functionName = customDimensions["prop__functionName"]
| extend status = customDimensions["prop__status"]
| extend details = customDimensions["prop__Details"] 
| extend reason = customDimensions["prop__reason"]
| where severityLevel >= 1 // to see all logs of severity level "Information" or greater.
| where instanceId == orchestrationInstanceID
| sort by timestamp asc 

Log coda di controllo e ID partizione

La query seguente cerca tutte le attività associate alla coda di controllo instanceId. Specificare il valore per instanceID in orchestrationInstanceID e l'ora di inizio della query in start.

let orchestrationInstanceID = "XXXXXX"; // edit this
let start = datetime(XXXX-XX-XXTXX:XX:XX); // edit this
traces  // determine control queue for this orchestrator
| where timestamp > start and timestamp < start + 1h 
| extend instanceId = customDimensions["prop__TargetInstanceId"] 
| extend partitionId = tostring(customDimensions["prop__PartitionId"])
| where partitionId contains "control" 
| where instanceId == orchestrationInstanceID
| join kind = rightsemi(
traces  
| where timestamp > start and timestamp < start + 1h 
| where customDimensions.Category == "DurableTask.AzureStorage" 
| extend taskName = customDimensions["EventName"]
| extend eventType = customDimensions["prop__EventType"] 
| extend extendedSession = customDimensions["prop__IsExtendedSession"]
| extend account = customDimensions["prop__Account"] 
| extend details = customDimensions["prop__Details"] 
| extend instanceId = customDimensions["prop__InstanceId"] 
| extend messageId = customDimensions["prop__MessageId"] 
| extend executionId = customDimensions["prop__ExecutionId"] 
| extend age = customDimensions["prop__Age"] 
| extend latencyMs = customDimensions["prop__LatencyMs"] 
| extend dequeueCount = customDimensions["prop__DequeueCount"] 
| extend partitionId = tostring(customDimensions["prop__PartitionId"])
| extend eventCount = customDimensions["prop__TotalEventCount"] 
| extend taskHub = customDimensions["prop__TaskHub"] 
| extend pid = customDimensions["ProcessId"]
| extend appName = cloud_RoleName
| extend newEvents = customDimensions["prop__NewEvents"]
) on partitionId
| sort by timestamp asc
| project timestamp, appName, severityLevel, pid, taskName, eventType, message, details, messageId, partitionId, instanceId, executionId, age, latencyMs, dequeueCount, eventCount, newEvents, taskHub, account, extendedSession, sdkVersion

Riferimenti alle colonne di Application Insights per le query di Durable Functions

Nella tabella seguente sono elencate le colonne proiettate dalle query precedenti e dalle relative descrizioni.

colonna Descrizione
pid ID processo dell'istanza dell'app per le funzioni. Tale valore è utile per verificare se il processo è stato riciclato durante l'esecuzione di un'orchestrazione.
nomeAttività Nome dell'evento registrato.
eventType Il tipo di messaggio, che di solito rappresenta il lavoro svolto da un orchestratore. Per un elenco completo dei valori possibili e delle relative descrizioni, vedere EventType.cs.
extendedSession Valore booleano che indica se le sessioni estese sono abilitate.
Conto Account di archiviazione usato dall'app.
details Informazioni aggiuntive su un evento specifico, se disponibile.
instanceId ID per una determinata orchestrazione o istanza di entità.
ID messaggio ID univoco di Archiviazione di Azure per un determinato messaggio della coda. Questo valore viene più comunemente visualizzato negli eventi di traccia ReceivedMessage, ProcessingMessage ed DeletingMessage. Questo valore non è presente negli eventi SendingMessage perché l'ID del messaggio viene generato da Archiviazione di Azure after il messaggio viene inviato.
ID di esecuzione ID dell'esecuzione dell'agente di orchestrazione, che cambia a ogni richiamo di continue-as-new.
età Numero di millisecondi da quando un messaggio è stato messo in coda. Un numero elevato spesso indica problemi di prestazioni. Un'eccezione è il tipo di messaggio TimerFired, che potrebbe avere un valore di validità elevato a seconda della durata del timer.
latencyMs Numero di millisecondi impiegato da un'operazione di archiviazione.
dequeueCount Numero di volte in cui un messaggio è rimosso dalla coda. In circostanze normali, questo valore è sempre 1. Se sono più di uno, potrebbe esserci un problema.
ID di partizione Nome della coda associata a questo log.
conteggio totale eventi Numero di eventi di cronologia coinvolti nell'azione corrente.
taskHub ** Nome dell'hub delle attività.
nuoviEventi Elenco delimitato da virgole di eventi della cronologia scritti nella tabella Cronologia nell'archiviazione.

Problemi di gestione delle connessioni nel piano a consumo

Le app in esecuzione nel piano a consumo di Funzioni di Azure sono soggette a limiti di connessione. I sintomi comuni includono:

  • Errori di connettività intermittenti quando si chiamano funzioni di attività o servizi esterni.
  • Orchestrazioni che falliscono sporadicamente sotto carico di lavoro.
  • Errori di esaurimento dei socket nei log.

Per ridurre l'utilizzo della connessione, usare HttpClientFactory o condividere client statici invece di creare nuove HttpClient istanze in ogni chiamata di funzione. Per indicazioni dettagliate sul pool di connessioni e sulle procedure consigliate, vedere Gestire le connessioni in Funzioni di Azure.

Suggerimenti generali

Suggerimento

Prima di approfondire specifici passaggi per la risoluzione dei problemi, assicurarsi che l'app usi la versione più recente dell'estensione Durable Functions. Nella maggior parte dei casi, l'uso della versione più recente riduce i problemi noti già segnalati da altri utenti. Per istruzioni su come effettuare l'aggiornamento, vedere aggiorna la versione di estensione di Durable Functions.

La scheda Diagnose e risolvere i problemi nel portale di Azure consente di monitorare e diagnosticare i problemi relativi all'applicazione e suggerire potenziali soluzioni. Per altre informazioni, vedere diagnostica dell'app di Azure Functions.

Ottenere supporto per i problemi di Durable Functions

Se non è possibile risolvere il problema usando questa guida, è possibile inviare un ticket di supporto aprendo la sezione Nuova richiesta di supporto nel pannello Support + troubleshooting della pagina dell'app per le funzioni nel portale Azure.

Screenshot della pagina della richiesta di supporto nella Azure portal.

Per domande e supporto della community, aprire un problema in uno dei GitHub repository seguenti. Quando si segnala un bug, includere informazioni come GLI ID istanza interessati, gli intervalli di tempo in formato UTC che mostrano il problema, il nome dell'applicazione (se possibile) e l'area di distribuzione per velocizzare le indagini.