Procedure consigliate per .NET SDK di Azure Cosmos DB

SI APPLICA A: NoSQL

Questo articolo illustra le procedure consigliate per l'uso di Azure Cosmos DB .NET SDK. Seguendo queste procedure, sarà possibile migliorare la latenza, la disponibilità e migliorare le prestazioni complessive.

Guardare il video seguente per altre informazioni sull'uso di .NET SDK da un tecnico di Azure Cosmos DB.

Elenco di controllo

Selezionato Oggetto Dettagli/Collegamenti
Versione dell'SDK Usare sempre la versione più recente di Azure Cosmos DB SDK disponibile per ottenere prestazioni ottimali.
Client singleton Usare una istanza singola di CosmosClient per la durata dell'applicazione per prestazioni migliori.
Aree Assicurarsi di eseguire l'applicazione nella stessa area di Azure dell'account Azure Cosmos DB, laddove possibile, per ridurre la latenza. Abilitare da 2 a 4 aree e replicare gli account in più aree per ottenere la migliore disponibilità. Per i carichi di lavoro di produzione, abilitare il failover gestito dal servizio. In assenza di questa configurazione, l'account riscontrerà perdite di disponibilità di scrittura per tutta la durata dell'interruzione dell'area di scrittura, perché il failover manuale avrà esito negativo a causa della mancanza di connettività dell'area. Per informazioni su come aggiungere più aree usando .NET SDK, vedere qui
Disponibilità e failover Impostare ApplicationPreferredRegions o ApplicationRegion nell'SDK v3 e PreferredLocations nell'SDK v2 usando l'elenco Aree preferite. Durante i failover, le operazioni di scrittura vengono inviate all'area di scrittura corrente e tutte le letture vengono inviate alla prima area all'interno dell'elenco delle aree preferite. Per altre informazioni sui meccanismi di failover a livello di area, vedere la Guida alla risoluzione dei problemi di disponibilità.
CPU È possibile che si verifichino problemi di connettività/disponibilità a causa della mancanza di risorse nel computer client. Monitorare l'utilizzo della CPU nei nodi che eseguono il client Azure Cosmos DB e aumentare le prestazioni o il numero di istanze se l'utilizzo è elevato.
Hosting Usare l'elaborazione host a 64 bit Windows per ottenere prestazioni ottimali, quando possibile. Per i carichi di lavoro di produzione sensibili alla latenza in modalità diretta, è consigliabile usare almeno macchine virtuali con 4 core e 8 GB di memoria quando possibile.
Modalità di connettività Usare la modalità diretta per ottenere prestazioni ottimali. Per istruzioni su come eseguire questa operazione, vedere la documentazione dell'SDK V3 o la documentazione dell'SDK V2.
Rete Se si usa una macchina virtuale per eseguire l'applicazione, abilitare Rete accelerata nella macchina virtuale per evitare i colli di bottiglia dovuti a traffico elevato e ridurre la latenza o l'instabilità della CPU. È anche possibile valutare l'utilizzo di una macchina virtuale di livello superiore in cui l'utilizzo massimo della CPU è inferiore al 70%.
Esaurimento delle porte temporanee Per le connessioni occasionali o sporadiche, le proprietà IdleConnectionTimeout e PortReuseMode vengono impostate su PrivatePortPool. La proprietà IdleConnectionTimeout consente di controllare il tempo trascorso il quale le connessioni inutilizzate vengono chiuse. In questo modo si riduce il numero di connessioni inutilizzate. Per impostazione predefinita, le connessioni inattive sono mantenute aperte per un periodo illimitato. Il valore impostato deve essere maggiore o uguale a 10 minuti. I valori consigliati sono compresi tra 20 minuti e 24 ore. La proprietà PortReuseMode consente all'SDK di usare un piccolo pool di porte temporanee per vari endpoint di destinazione di Azure Cosmos DB.
Usare modelli async/await Evitare le chiamate di blocco: Task.Result, Task.Wait e Task.GetAwaiter().GetResult(). L'intero stack di chiamate è asincrono per trarre vantaggio dai modelli async/await. Molte chiamate di blocco sincrone causano la scadenza del pool di thread e tempi di risposta degradati.
Timeout end-to-end Per ottenere timeout end-to-end, è necessario usare entrambi i parametri RequestTimeout e CancellationToken. Per informazioni dettagliate, vedere la guida alla risoluzione dei problemi di timeout.
Logica di ripetizione dei tentativi Per altre informazioni sugli errori per cui è necessario ripetere i tentativi e sugli errori per cui i tentativi vengono ripetuti dall'SDK, vedere la guida alla progettazione. Per gli account configurati con più aree, esistono alcuni scenari in cui l'SDK esegue automaticamente ulteriori tentativi in altre aree. Per informazioni dettagliate sull'implementazione specifica di .NET, vedere il repository di origine dell'SDK.
Memorizzazione nella cache dei nomi di database/raccolta Recuperare i nomi dei database e dei contenitori dalla configurazione oppure memorizzarli nella cache all'avvio. Le chiamate come ReadDatabaseAsync o ReadDocumentCollectionAsync e CreateDatabaseQuery o CreateDocumentCollectionQuery genereranno chiamate di metadati al servizio, il cui utilizzo viene conteggiato ai fini del limite di UR riservate dal sistema. Inoltre, l'operazione CreateIfNotExist deve essere usata una sola volta per configurare il database. Nel complesso, queste operazioni devono essere eseguite raramente.
Supporto bulk Negli scenari in cui potrebbe non essere necessario ottimizzare la latenza, è consigliabile abilitare il supporto bulk per il dump di grandi volumi di dati.
Query parallele Azure Cosmos DB SDK supporta l'esecuzione di query in parallelo per migliorare la latenza e la velocità effettiva nelle query. È consigliabile impostare la proprietà MaxConcurrency in QueryRequestsOptions sul numero di partizioni disponibili. Se non si è a conoscenza del numero di partizioni, iniziare usando int.MaxValue, che offre la latenza migliore. Ridurre quindi il numero fino a quando non rientra nelle restrizioni delle risorse dell'ambiente per evitare problemi di CPU elevata. Impostare inoltre MaxBufferedItemCount sul numero previsto di risultati restituiti per limitare il numero di risultati di prelettura.
Backoff dei test delle prestazioni Quando si eseguono test sull'applicazione, è necessario implementare i backoff a intervalli RetryAfter. Rispettando il backoff si garantiscono tempi di attesa minimi tra i tentativi.
Indicizzazione I criteri di indicizzazione di Azure Cosmos DB consentono anche di specificare i percorsi dei documenti da includere o escludere dall'indicizzazione usando i percorsi di indicizzazione (IndexingPolicy.IncludedPaths e IndexingPolicy.ExcludedPaths). Assicurarsi di escludere i percorsi inutilizzati dall'indicizzazione per scritture più veloci. Per altre informazioni su come creare indici con l'SDK, vedere Suggerimenti sulle prestazioni per .NET SDK v3.
Dimensioni del documento L'addebito per le richieste per un'operazione specifica è correlato direttamente alle dimensioni del documento. È consigliabile ridurre le dimensioni dei documenti, in quanto le operazioni su documenti di grandi dimensioni costano più delle operazioni su documenti più piccoli.
Aumentare il numero di thread/attività Poiché le chiamate ad Azure Cosmos DB vengono eseguite sulla rete, può essere necessario modificare il grado di concorrenza delle richieste in modo che i tempi di attesa dell'applicazione client tra le richieste siano minimi. Se si usa Task Parallel Library di .NET, ad esempio, creare centinaia di attività di lettura o scrittura in Azure Cosmos DB.
Abilitazione delle metriche delle query Per aumentare la registrazione delle esecuzioni di query back-end, è possibile abilitare le metriche delle query SQL usando .NET SDK. Per altre informazioni su come raccogliere metriche delle query SQL, vedere Metriche e prestazioni delle query.
Registrazione SDK Registrare la diagnostica dell'SDK per gli scenari in sospeso, ad esempio le eccezioni o quando le richieste superano una latenza prevista.
DefaultTraceListener DefaultTraceListener pone problemi di prestazioni negli ambienti di produzione causando colli di bottiglia elevati di CPU e I/O. Assicurarsi di usare le versioni più recenti dell'SDK o rimuovere DefaultTraceListener dall'applicazione
Evitare l'uso di caratteri speciali negli identificatori L'uso dei caratteri seguenti è limitato e non è consentito in alcuni identificatori: '/', '\', '?', '#'. È consigliabile non usare caratteri speciali negli identificatori come nome del database, nome della raccolta, ID elemento o chiave di partizione per evitare comportamenti imprevisti.

Acquisire la diagnostica

Tutte le risposte nell'SDK, inclusa CosmosException, hanno una proprietà Diagnostics. Questa proprietà registra tutte le informazioni correlate alla singola richiesta, inclusi i tentativi effettuati o eventuali errori temporanei.

La diagnostica viene restituita come stringa. La stringa cambia con ogni versione, perché viene migliorata per la risoluzione dei problemi relativi a scenari diversi. Con ogni versione dell'SDK, la stringa include modifiche alla formattazione che causano un'interruzione. Non analizzare la stringa per evitare modifiche che causano interruzioni. L'esempio di codice seguente illustra come leggere i log di diagnostica usando .NET SDK:

try
{
    ItemResponse<Book> response = await this.Container.CreateItemAsync<Book>(item: testItem);
    if (response.Diagnostics.GetClientElapsedTime() > ConfigurableSlowRequestTimeSpan)
    {
        // Log the response.Diagnostics.ToString() and add any additional info necessary to correlate to other logs 
    }
}
catch (CosmosException cosmosException)
{
    // Log the full exception including the stack trace with: cosmosException.ToString()
    
    // The Diagnostics can be logged separately if required with: cosmosException.Diagnostics.ToString()
}

// When using Stream APIs
ResponseMessage response = await this.Container.CreateItemStreamAsync(partitionKey, stream);
if (response.Diagnostics.GetClientElapsedTime() > ConfigurableSlowRequestTimeSpan || !response.IsSuccessStatusCode)
{
    // Log the diagnostics and add any additional info necessary to correlate to other logs with: response.Diagnostics.ToString()
}

Procedure consigliate per le connessioni HTTP

.NET SDK usa HttpClient per eseguire richieste HTTP indipendentemente dalla modalità di connettività configurata. Nella modalità diretta HTTP viene usato per le operazioni sui metadati e nella modalità gateway viene usato sia per le operazioni sul piano dati che per le operazioni sui metadati. Uno degli aspetti fondamentali di HttpClient consiste nell'assicurarsi che HttpClient possa reagire alle modifiche del DNS nell'account personalizzando la durata delle connessioni in pool. Se le connessioni in pool vengono mantenute aperte, non reagiscono alle modifiche DNS. Questa impostazione impone la chiusura periodica delle connessioni in pool, per garantire che l'applicazione reagisca alle modifiche del DNS. È consigliabile personalizzare questo valore in base alla modalità di connettività e al carico di lavoro in uso per bilanciare l'impatto sulle prestazioni della creazione frequente di nuove connessioni, con la necessità di reagire alle modifiche del DNS (disponibilità). Un valore di 5 minuti costituisce un valore iniziale ottimale che può essere aumentato se influisce sulle prestazioni, in particolare per la modalità gateway.

È possibile inserire un oggetto HttpClient personalizzato tramite CosmosClientOptions.HttpClientFactory, ad esempio:

// Use a Singleton instance of the SocketsHttpHandler, which you can share across any HttpClient in your application
SocketsHttpHandler socketsHttpHandler = new SocketsHttpHandler();
// Customize this value based on desired DNS refresh timer
socketsHttpHandler.PooledConnectionLifetime = TimeSpan.FromMinutes(5);

CosmosClientOptions cosmosClientOptions = new CosmosClientOptions()
{
    // Pass your customized SocketHttpHandler to be used by the CosmosClient
    // Make sure `disposeHandler` is `false`
    HttpClientFactory = () => new HttpClient(socketsHttpHandler, disposeHandler: false)
};

// Use a Singleton instance of the CosmosClient
return new CosmosClient("<connection-string>", cosmosClientOptions);

Se si usa l'inserimento delle dipendenze .NET, è possibile semplificare il processo singleton:

SocketsHttpHandler socketsHttpHandler = new SocketsHttpHandler();
// Customize this value based on desired DNS refresh timer
socketsHttpHandler.PooledConnectionLifetime = TimeSpan.FromMinutes(5);
// Registering the Singleton SocketsHttpHandler lets you reuse it across any HttpClient in your application
services.AddSingleton<SocketsHttpHandler>(socketsHttpHandler);

// Use a Singleton instance of the CosmosClient
services.AddSingleton<CosmosClient>(serviceProvider =>
{
    SocketsHttpHandler socketsHttpHandler = serviceProvider.GetRequiredService<SocketsHttpHandler>();
    CosmosClientOptions cosmosClientOptions = new CosmosClientOptions()
    {
        HttpClientFactory = () => new HttpClient(socketsHttpHandler, disposeHandler: false)
    };

    return new CosmosClient("<connection-string>", cosmosClientOptions);
});

Procedure consigliate per l'uso della modalità gateway

Aumentare System.Net MaxConnections per host quando si usa la modalità gateway. Le richieste di Azure Cosmos DB vengono effettuate tramite HTTPS/REST quando si usa la modalità gateway. Sono soggette al limite di connessione predefinito per nome host o indirizzo IP. Potrebbe essere necessario impostare MaxConnections su un valore più alto (da 100 a 1.000) per consentire alla libreria client di usare più connessioni simultanee ad Azure Cosmos DB. In .NET SDK 1.8.0 e versioni successive il valore predefinito per ServicePointManager.DefaultConnectionLimit è 50. Per modificare il valore, è possibile impostare CosmosClientOptions.GatewayModeMaxConnectionLimit su un valore più alto.

Procedure consigliate per carichi di lavoro con un numero elevato di scritture

Per i carichi di lavoro con un numero elevato di payload di creazione, impostare l'opzione della richiesta EnableContentResponseOnWrite su false. Il servizio non restituirà più la risorsa creata o aggiornata all'SDK. In genere, poiché l'applicazione ha l'oggetto che viene creato, non è necessario che il servizio lo restituisca. I valori dell'intestazione sono ancora accessibili, ad esempio un addebito della richiesta. La disabilitazione della risposta al contenuto può contribuire a migliorare le prestazioni, perché l'SDK non deve più allocare memoria o serializzare il corpo della risposta. Riduce inoltre l'uso della larghezza di banda di rete per migliorare ulteriormente le prestazioni.

Importante

L'impostazione di EnableContentResponseOnWrite su false disabiliterà anche la risposta da un'operazione trigger.

Procedure consigliate per le applicazioni multi-tenant

Le applicazioni che distribuiscono l'utilizzo tra più tenant in cui ogni tenant è rappresentato da un database, un contenitore o una chiave di partizione diversa all'interno dello stesso account Azure Cosmos DB deve usare un'istanza singola del client. Un'istanza singola client può interagire con tutti i database, i contenitori e le chiavi di partizione all'interno di un account e la procedura consigliata prevede l'utilizzo del modello singleton.

Tuttavia, quando ogni tenant è rappresentato da un account Azure Cosmos DB diverso, è necessario creare un'istanza del client separata per ogni account. Il modello singleton è ancora valido per ogni client (un client per ogni account per la durata dell'applicazione), ma se il volume dei tenant è elevato, il numero di client può essere difficile da gestire. Le connessioni possono aumentare oltre i limiti dell'ambiente di calcolo e causare problemi di connettività.

In questi casi è consigliabile:

  • Comprendere le limitazioni dell'ambiente di calcolo (risorse di CPU e di connessione). È consigliabile usare macchine virtuali con almeno 4 core e 8 GB di memoria quando possibile.
  • In base alle limitazioni dell'ambiente di calcolo, determinare il numero di istanze del client (e quindi il numero di tenant) che una singola istanza di calcolo può gestire. È possibile stimare il numero di connessioni che verranno aperte per client a seconda della modalità di connessione scelta.
  • Valutare la distribuzione del tenant tra le istanze. Se ogni istanza di calcolo può gestire correttamente una quantità limitata di tenant specifica, il bilanciamento del carico e il routing dei tenant a istanze di calcolo diverse consentirebbe di aumentare le istanze in base all'aumento del numero di tenant.
  • Per i carichi di lavoro occasionali, è consigliabile usare una cache utilizzata meno di frequente come struttura per contenere le istanze del client ed eliminare i client per i tenant a cui non è stato eseguito l'accesso entro un intervallo di tempo specifico. Un'opzione in .NET è MemoryCacheEntryOptions, che consente di usare RegisterPostEvictionCallback per eliminare i client inattivi e SetSlidingExpiration per definire il tempo massimo di conservazione delle connessioni inattive.
  • Valutare l'uso della modalità gateway per ridurre il numero di connessioni di rete.
  • Quando si usa la modalità diretta è consigliabile modificare CosmosClientOptions.IdleTcpConnectionTimeout e CosmosClientOptions.PortReuseMode in configurazione modalità diretta per chiudere le connessioni inutilizzate e mantenere sotto controllo il volume di connessioni.

Passaggi successivi

Per un'applicazione di esempio che viene usata per valutare Azure Cosmos DB per scenari a prestazioni elevate su un numero ridotto di computer client, vedere Test delle prestazioni e della scalabilità con Azure Cosmos DB.

Per altre informazioni sulla progettazione dell'applicazione per scalabilità e prestazioni elevate, vedere l'articolo relativo a partizionamento e ridimensionamento in Azure Cosmos DB.

Si sta tentando di pianificare la capacità per una migrazione ad Azure Cosmos DB? È possibile usare le informazioni del cluster di database esistente per la pianificazione della capacità.