Diagnosticare e risolvere le eccezioni di timeout delle richieste di Azure Cosmos DB SDK per .NET
SI APPLICA A: NoSQL
L'errore HTTP 408 si verifica se l'SDK non è stato in grado di completare la richiesta prima del raggiungimento del limite di timeout.
È importante assicurarsi che la progettazione dell'applicazione segua la guida per la progettazione di applicazioni resilienti con SDK di Azure Cosmos DB per assicurarsi che reagisca correttamente alle diverse condizioni di rete. L'applicazione deve disporre di tentativi sul posto per gli errori di timeout, in quanto normalmente sono previsti in un sistema distribuito.
Quando si valuta il caso per gli errori di timeout:
- Qual è l'impatto misurato in volume delle operazioni interessate rispetto alle operazioni completate correttamente? Rientra nei contratti di servizio?
- La disponibilità / latenza P99 è interessata?
- Gli errori interessano tutte le istanze dell'applicazione o solo un sottoinsieme? I problemi ridotti a un sottoinsieme di istanze in genere sono correlati a tale istanze.
Personalizzare il timeout nell'SDK .NET di Azure Cosmos DB
L'SDK ha due alternative distinte per controllare i timeout, ognuna con un ambito diverso.
Timeout a livello di richiesta
La configurazione CosmosClientOptions.RequestTimeout
(o ConnectionPolicy.RequestTimeout
per SDK v2) consente di impostare un timeout per la richiesta di rete dopo che la richiesta ha lasciato l'SDK ed è in rete, fino a quando non viene ricevuta una risposta.
La configurazione CosmosClientOptions.OpenTcpConnectionTimeout
(o ConnectionPolicy.OpenTcpConnectionTimeout
per SDK v2) consente di impostare un timeout per il tempo impiegato per l'apertura di una connessione iniziale. Una volta aperta una connessione, le richieste successive la useranno.
Un'operazione avviata da un utente può estendersi su più richieste di rete, ad esempio per i retry. Queste due configurazioni sono per richiesta, non end-to-end per un'operazione.
CancellationToken
Tutte le operazioni asincrone nell'SDK hanno un parametro CancellationToken facoltativo. Questo parametro CancellationToken viene usato nell'intera operazione, in tutte le richieste di rete e i retry. Tra le richieste di rete, il token di annullamento potrebbe essere controllato e un'operazione potrebbe essere annullata se il token correlato è scaduto. Il token di annullamento deve essere usato per definire un timeout previsto approssimativo nell'ambito dell'operazione.
Nota
Il parametro CancellationToken
è un meccanismo in cui la libreria verificherà l'annullamento quando non causerà uno stato non valido. L'operazione potrebbe non annullare esattamente alla scadenza del tempo definito nell'annullamento. Dopo la scadenza, eseguirà invece l'annullamento quando sarà sicuro farlo.
Passaggi per la risoluzione dei problemi
L'elenco seguente contiene le cause note e le soluzioni per le eccezioni di timeout delle richieste.
CosmosOperationCanceledException
Questo tipo di eccezione è comune quando l'applicazione passa CancellationTokens alle operazioni SDK. L'SDK controlla lo stato di CancellationToken
tra un retry e l'altro e, se CancellationToken
viene annullato, l'operazione corrente viene interrotta con questa eccezione.
L'elemento Message
/ ToString()
dell'eccezione indicherà anche lo stato di CancellationToken
tramite Cancellation Token has expired: true
e includerà anche la diagnostica contenente il contesto dell'annullamento per le richieste coinvolte.
Queste eccezioni possono essere usate con sicurezza per i retry ed essere considerate come timeout dal punto di vista dei retry.
Soluzione
Verificare l'ora configurata in CancellationToken
, assicurarsi che sia maggiore di RequestTimeout e di CosmosClientOptions.OpenTcpConnectionTimeout (se si usa la modalità diretta).
Se il tempo disponibile in CancellationToken
è minore dei timeout configurati e l'SDK ha problemi di connettività temporanei, l'SDK non riuscirà e riprovare e genererà l'eccezione CosmosOperationCanceledException
.
Utilizzo elevato della CPU
L'utilizzo elevato della CPU è il caso più comune. Per una latenza ottimale, l'utilizzo della CPU deve essere approssimativamente del 40%. Usare 10 secondi come intervallo per monitorare l'utilizzo massimo (non medio) della CPU. I picchi di CPU sono più comuni con query tra partizioni in cui potrebbero essere eseguite più connessioni per una singola query.
I timeout conterranno la diagnostica, che contiene:
"systemHistory": [
{
"dateUtc": "2021-11-17T23:38:28.3115496Z",
"cpu": 16.731,
"memory": 9024120.000,
"threadInfo": {
"isThreadStarving": "False",
....
}
},
{
"dateUtc": "2021-11-17T23:38:28.3115496Z",
"cpu": 16.731,
"memory": 9024120.000,
"threadInfo": {
"isThreadStarving": "False",
....
}
},
...
]
- Se i valori
cpu
sono superiori al 70%, è probabile che il timeout sia causato dall'esaurimento della CPU. In questo caso la soluzione consiste nel ricercare l'origine dell'utilizzo elevato della CPU e ridurre l'uso o nel ridimensionare il computer a dimensioni di risorse più elevate. - Se i nodi
threadInfo/isThreadStarving
hanno valoriTrue
, la causa è la scadenza dei thread. In questo caso, la soluzione consiste nel ricercare l'origine della scadenza del thread (thread potenzialmente bloccati) o nel ridimensionare il computer a dimensioni di risorse più elevate. - Se l'intervallo di tempo
dateUtc
tra le misurazioni non è di circa 10 secondi, indica anche la contesa nel pool di thread. La CPU viene misurata come un'attività indipendente accodata nel pool di thread ogni 10 secondi, se il tempo compreso tra la misurazione è più lungo, indica che le attività asincrone non possono essere elaborate in modo tempestivo. Gli scenari più comuni sono quando si eseguono chiamate bloccanti su codice asincrono nel codice dell'applicazione.
Soluzione
L'applicazione client che usa l'SDK deve essere ridimensionata o ridotta.
La disponibilità del socket o della porta potrebbe essere bassa
Durante l'esecuzione in Azure, i client che usano .NET SDK possono raggiungere l'esaurimento della porta SNAT (PAT) di Azure.
Soluzione 1
Con l'esecuzione in macchine virtuali di Azure, seguire la Guida all'esaurimento delle porte SNAT.
Soluzione 2
Se si esegue il Servizio app di Azure, seguire la guida alla risoluzione degli errori di connessione e usare la diagnostica del Servizio app.
Soluzione 3
Se si esegue Funzioni di Azure, verificare di seguire la raccomandazione di Funzioni di Azure, ossia di mantenere client singleton o statici per tutti i servizi coinvolti (incluso Azure Cosmos DB). Controllare i limiti del servizio in base al tipo e alle dimensioni dell'hosting dell'app per le funzioni.
Soluzione 4
Se si usa un proxy HTTP, assicurarsi che possa supportare il numero di connessioni configurate in ConnectionPolicy
dell'SDK. In caso contrario, verranno riscontrati problemi di connessione.
Creare più istanze client
La creazione di più istanze client può causare conflitti di connessione e problemi di timeout. La Diagnostica contiene due proprietà pertinenti:
{
"NumberOfClientsCreated":X,
"NumberOfActiveClients":Y,
}
NumberOfClientsCreated
tiene traccia del numero di volte in cui è stato creato un CosmosClient
all'interno dello stesso AppDomain e NumberOfActiveClients
tiene traccia dei client attivi (non eliminati). L'aspettativa è che se viene seguito il modello singleton, X
corrisponde al numero di account con cui l'applicazione funziona e che X
è uguale a Y
.
Se X
è maggiore di Y
, significa che l'applicazione sta creando ed eliminando istanze client. Ciò può causare una contesa di connessione e/o una contesa della CPU.
Soluzione
Seguire i suggerimenti sulle prestazioni e utilizzare una singola istanza di CosmosClient per account in un intero processo. Evitare di creare ed eliminare i client.
Chiavi di partizione ad accesso frequente
Azure Cosmos DB distribuisce in modo uniforme la velocità effettiva complessiva con provisioning tra partizioni fisiche. Quando è presente una partizione ad accesso frequente, una o più chiavi di partizione logica in una partizione fisica usano tutte le unità richiesta della partizione fisica al secondo (UR/s). Allo stesso tempo, le UR/s in altre partizioni fisiche non verranno utilizzate. Come sintomo, le UR/sec totali consumate saranno inferiori alle UR/sec complessive di cui è stato effettuato il provisioning nel database o nel contenitore, ma si noterà comunque una limitazione (429s) sulle richieste rispetto alla chiave di partizione logica ad accesso frequente. Utilizzare la metrica di consumo di UR normalizzata per verificare se il carico di lavoro stia riscontrando una partizione ad accesso frequente.
Soluzione
Scegliere una chiave di partizione valida che distribuisca in modo uniforme il volume e l'archiviazione delle richieste. Leggere come modificare la chiave di partizione.
Livello elevato di concorrenza
L'applicazione sta eseguendo un livello elevato di concorrenza, cosa che può portare a contese sul canale.
Soluzione
L'applicazione client che usa l'SDK deve essere ridimensionata o ridotta.
Richieste o risposte di grandi dimensioni
Richieste o risposte di grandi dimensioni possono causare un blocco head-of-line sul canale ed esacerbare la contesa, anche con un grado di concorrenza relativamente basso.
Soluzione
L'applicazione client che usa l'SDK deve essere ridimensionata o ridotta.
Il tasso di errore rientra nel contratto di servizio di Azure Cosmos DB
L'applicazione deve essere in grado di gestire gli errori temporanei e riprovare quando necessario. Eventuali eccezioni 408 non vengono ritentate perché nei percorsi di creazione non è possibile sapere se il servizio ha creato o meno l'elemento. L'invio dello stesso elemento per la creazione causerà un'eccezione di conflitto. La logica di business delle applicazioni utente potrebbe avere una logica personalizzata per gestire i conflitti, che potrebbe interrompere l'ambiguità di un elemento esistente rispetto al conflitto dovuto a un nuovo tentativo di creazione.
Il tasso di errore viola il contratto di servizio di Azure Cosmos DB
Contattare il supporto di Azure.
Passaggi successivi
- Diagnosticare e risolvere i problemi che si verificano durante l'uso di .NET SDK per Azure Cosmos DB.
- Informazioni sulle linee guida sulle prestazioni per .NET v3 e .NET v2.