Condividi tramite


Procedure consigliate per Azure Cosmos DB .NET SDK

SI APPLICA A: NoSQL

Questo articolo illustra le procedure consigliate per l'uso di Azure Cosmos DB .NET SDK. Seguendo queste procedure, è 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

Casella di controllo Oggetto Descrizione
Versione dell'SDK Usare sempre la versione più recente di Azure Cosmos DB SDK disponibile per ottenere prestazioni ottimali.
Client Singleton Per prestazioni migliori, usare un'CosmosClient di per tutta la durata dell'applicazione.
Regioni Assicurarsi di eseguire l'applicazione nella stessa area di Azure dell'account Azure Cosmos DB, quando possibile, per ridurre la latenza. Abilitare da due a quattro 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 riscontra perdite di disponibilità in scrittura per tutta la durata dell'interruzione dell'area di scrittura, perché non è possibile eseguire il failover manuale a causa della mancanza di connettività nell'area. Per informazioni su come aggiungere più aree usando .NET SDK, vedere questa esercitazione.
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 Potrebbero verificarsi 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 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, vedere la documentazione di V3 SDK o la documentazione di V2 SDK.
Rete Se si usa una macchina virtuale per eseguire l'applicazione, abilitare la 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 prendere in considerazione l'uso di una macchina virtuale di fascia superiore in cui l'utilizzo massimo della CPU è inferiore a 70%.
Esaurimento della porta temporanea 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 criteri 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 criteri 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 altre informazioni, vedere la guida alla risoluzione dei problemi di timeout.
Logica di ripetizione 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 riprova automaticamente 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. Chiamate come ReadDatabaseAsync o ReadDocumentCollectionAsync e CreateDatabaseQuery o CreateDocumentCollectionQuery comportano chiamate di metadati al servizio, che consumano dal limite di RU riservato del sistema. Inoltre, l'operazione CreateIfNotExist deve essere usata una sola volta per configurare il database. Nel complesso, queste operazioni devono essere eseguite raramente.
Supporto in blocco Negli scenari in cui potrebbe non essere necessario ottimizzare la latenza, è consigliabile abilitare il supporto per operazioni in blocco per lo scarico 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 Criteri di indicizzazione.
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 sono più costose rispetto alle operazioni su documenti di piccole dimensioni.
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 di 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 dell'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 a 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 Alcuni caratteri sono limitati e non possono essere usati 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.

Gestione delle dipendenze di Newtonsoft.Json

Informazioni generali

Azure Cosmos DB .NET SDK ha una dipendenza da Newtonsoft.Json per le operazioni di serializzazione JSON. Questa dipendenza non viene gestita automaticamente . È necessario aggiungere Newtonsoft.Json in modo esplicito come dipendenza diretta nel progetto.

L'SDK viene compilato internamente in Newtonsoft.Json 10.x, che presenta una vulnerabilità di sicurezza nota. Anche se l'SDK è tecnicamente compatibile con la versione 10.x e l'uso dell'SDK di Newtonsoft.Json non è soggetto al problema di sicurezza segnalato, è comunque consigliabile usare la versione 13.0.3 o successiva per evitare potenziali problemi di sicurezza o conflitti. Le versioni 13.x includono modifiche di rilievo, ma i modelli di utilizzo dell'SDK sono compatibili con queste modifiche.

Importante

Questa dipendenza è necessaria anche quando si usa System.Text.Json per i tipi definiti dall'utente tramite CosmosClientOptions.UseSystemTextJsonSerializerWithOptions, perché le operazioni interne dell'SDK usano ancora Newtonsoft.Json per i tipi di sistema.

Aggiungere Newtonsoft.Json sempre in modo esplicito la versione 13.0.3 o successiva come dipendenza diretta quando si usa Azure Cosmos DB .NET SDK v3. Non usare la versione 10.x a causa di vulnerabilità di sicurezza note.

Per progetti Standard .csproj

<ItemGroup>
  <PackageReference Include="Microsoft.Azure.Cosmos" Version="3.47.0" />
  <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
</ItemGroup>

Per i progetti che usano la gestione pacchetti centrale

Se il progetto usa Directory.Packages.props:

<Project>
  <ItemGroup>
    <PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.47.0" />
    <PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
  </ItemGroup>
</Project>

Risoluzione dei conflitti di versione

Informazioni di riferimento su Newtonsoft.Json mancanti

Se si verifica un errore di compilazione simile al seguente:

The Newtonsoft.Json package must be explicitly referenced with version >= 10.0.2. Please add a reference to Newtonsoft.Json or set the 'AzureCosmosDisableNewtonsoftJsonCheck' property to 'true' to bypass this check.

Questo errore viene generato intenzionalmente dalle destinazioni di compilazione di Cosmos DB SDK per assicurarsi che la dipendenza sia configurata correttamente.

Soluzione per le applicazioni:

Aggiungere un riferimento esplicito a Newtonsoft.Json, come illustrato nella sezione Configurazione consigliata precedente.

Soluzione per le librerie:

Se si sta creando una libreria (non un'applicazione) e si intende rinviare la dipendenza Newtonsoft.Json ai consumatori della libreria, è possibile ignorare questa verifica impostando la proprietà MSBuild in .csproj:

<PropertyGroup>
  <AzureCosmosDisableNewtonsoftJsonCheck>true</AzureCosmosDisableNewtonsoftJsonCheck>
</PropertyGroup>

Avvertimento

Usare questo bypass solo quando si compilano librerie in cui gli utenti finali forniranno la dipendenza Newtonsoft.Json. Per le applicazioni, aggiungere sempre il riferimento esplicito.

Conflitti di versione del pacchetto

Se si verificano errori di compilazione come:

error NU1109: Detected package downgrade: Newtonsoft.Json from 13.0.4 to centrally defined 13.0.3

Soluzione:

  1. Identificare la versione richiesta controllando quali pacchetti necessitano di versioni più recenti:

    dotnet list package --include-transitive | Select-String "Newtonsoft.Json"
    
  2. Aggiornare la versione centralizzata del pacchetto in modo che corrisponda o superi la versione più recente richiesta:

    <PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
    
  3. Pulizia e ricompilazione:

    dotnet clean
    dotnet restore
    dotnet build
    

Compatibilità delle versioni

La tabella seguente illustra le versioni sicure minime consigliate di Newtonsoft.Json per ogni versione di Cosmos DB SDK. Anche se l'SDK può funzionare tecnicamente con 10.x, queste versioni non devono mai essere usate a causa di vulnerabilità di sicurezza.

Versione di Cosmos DB SDK Versione minima sicura Recommended
3.47.0+ 13.0.3 13.0.4
3.54.0+ 13.0.4 13.0.4

Suggerimento

Quando si usa .NET Aspire 13.0.0 o versione successiva, assicurarsi che Newtonsoft.Json sia alla versione 13.0.4 per evitare conflitti con i componenti di Azure di Aspire.

Migliori pratiche

  • Aggiungere sempre come dipendenza diretta : l'SDK non gestisce automaticamente questa dipendenza
  • Usare la versione 13.0.3 o successiva : non usare mai la versione 10.x nonostante la compatibilità tecnica, a causa di vulnerabilità di sicurezza note
  • Obbligatorio anche con System.Text.Json : è necessario includere Newtonsoft.Json anche quando si usa UseSystemTextJsonSerializerWithOptions, perché l'SDK lo usa internamente per i tipi di sistema
  • Aggiungere la versione in modo esplicito : non fare affidamento sulla risoluzione delle dipendenze transitive
  • Avvisi di monitoraggio - Trattare gli avvisi di downgrade del pacchetto NuGet (NU1109) come errori nelle pipeline CI/CD

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.

  • In modalità diretta, HTTP viene usato per le operazioni sui metadati
  • In modalità gateway, HTTP viene usato sia per il 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 forza la chiusura periodica delle connessioni in pool, assicurandosi che l'applicazione reagisca alle modifiche DNS. È consigliabile personalizzare questo valore in base alla modalità di connettività e al carico di lavoro per bilanciare l'effetto delle prestazioni della creazione frequente di nuove connessioni, con la necessità di reagire alle modifiche DNS (disponibilità). Un valore di 5 minuti sarebbe un buon inizio 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 .NET dependency injection, è possibile semplificare il processo del 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 payload di creazione massicci, impostare l'opzione di richiesta EnableContentResponseOnWrite su false. Il servizio non restituisce 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 disabilita anche la risposta da un'operazione di 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 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 carichi di lavoro sparsi, prendere in considerazione l'uso di una cache meno frequentemente usata come struttura per contenere le istanze client ed eliminare i client per i tenant a cui non si accede entro una finestra temporale. 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 nella configurazione in modalità diretta per chiudere le connessioni inutilizzate e mantenere sotto controllo il volume delle connessioni .

Passaggi successivi

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à.