Meilleures pratiques pour Azure Cosmos DB .NET SDK v3

S’APPLIQUE À : NoSQL

Cet article décrit les meilleures pratiques pour l’utilisation du kit de développement logiciel (SDK) .NET Azure Cosmos DB. Les pratiques suivantes vous aideront à améliorer la latence, la disponibilité et améliorer les performances globales.

Regardez la vidéo ci-dessous d’un ingénieur Azure Cosmos DB pour en savoir plus sur l’utilisation du kit SDK .NET !

Check-list

Activée Objet Détails/Liens
Version du SDK Utilisez toujours la dernière version du kit SDK Azure Cosmos DB disponible pour des performances optimales.
Client Singleton Utilisez une seule instance de CosmosClient pour la durée de vie de votre application pour de meilleures performances.
Régions Exécutez autant que possible votre application dans la même région Azure que celle dans laquelle se trouve votre compte Azure Cosmos DB. Activez les régions 2-4 et répliquez vos comptes dans plusieurs régions pour une disponibilité optimale. Pour les charges de travail de production, activez le basculement managé par le service. En l’absence de cette configuration, le compte subit une perte de disponibilité en écriture pendant toute la durée de la panne de la région d’écriture, car le basculement manuel échoue en raison d’un manque de connectivité de la région. Pour savoir comment ajouter plusieurs régions à l’aide du kit de développement logiciel (SDK) .NET, visitez ici
Disponibilité et basculements Définissez ApplicationPreferredRegions ou ApplicationRegion dans le kit SDK v3 et PreferredLocations dans le kit SDK v2 en utilisant la liste des régions préférées. Pendant les basculements, les opérations d’écriture sont envoyées à la région d’écriture en cours et toutes les lectures sont envoyées à la première région de la liste de régions de votre choix. Pour plus d’informations sur le mécanisme de basculement régional, consultez le Guide de résolution des problèmes de disponibilité.
UC Vous pouvez rencontrer des problèmes de connectivité/disponibilité en raison d’un manque de ressources sur votre ordinateur client. Surveillez l’utilisation du processeur sur les nœuds qui exécutent le client Azure Cosmos DB et effectuez un scale-up/out si l’utilisation est élevée.
Hosting Utilisez le traitement de l’hôte 64 bits Windows pour obtenir des performances optimales, dans la mesure du possible. Pour les charges de travail de production sensibles à la latence en mode direct, nous vous recommandons vivement d’utiliser des machines virtuelles avec au moins 4 cœurs et 8 Go de mémoire si possible.
Modes de connectivité Utilisez le Mode direct pour obtenir des performances optimales. Pour obtenir des instructions sur la procédure à suivre, consultez la documentation du kit de développement logiciel (SDK) v3 ou la documentation du kit de développement logiciel (SDK) v2.
Mise en réseau Si vous utilisez une machine virtuelle pour exécuter votre application, activez la Mise en réseau accélérée sur votre machine virtuelle pour faciliter les goulots d’étranglement dus à un trafic élevé et réduire la latence ou l’instabilité du processeur. Vous pouvez également envisager d’utiliser une Machine virtuelle de fin supérieure où l’utilisation maximale de l’UC est inférieure à 70%.
Épuisement des ports éphémères Pour les connexions éparses ou sporadiques, nous définissons IdleConnectionTimeout et PortReuseMode sur PrivatePortPool . La propriété IdleConnectionTimeout permet de contrôler le délai au terme duquel fermer les connexions inutilisées. Cela réduit le nombre de connexions inutilisées. Par défaut, les connexions inactives restent ouvertes indéfiniment. Cette valeur doit être supérieure ou égale à 10 minutes. Les valeurs recommandées sont comprises entre 20 minutes et 24 heures. La propriété PortReuseMode permet au kit SDK d’utiliser un petit pool de ports éphémères pour différents points de terminaison de destination Azure Cosmos DB.
Utiliser Async/Await Évitez les appels bloquants Task.Result, Task.Wait et Task.GetAwaiter().GetResult(). L’ensemble de la pile des appels est asynchrone afin de tirer parti des modèles async/await. De nombreux appels bloquants synchrones conduisent à une défaillance du pool de conversation et à des temps de réponse qui se dégradent.
Délais d’expiration de bout en bout Pour obtenir des délais d’expiration de bout en bout, vous devez utiliser les paramètres RequestTimeout et CancellationToken. Si vous souhaitez en savoir plus, veuillez consulter notre guide de résolution des problèmes liés au délai d’expiration.
Logique de nouvelle tentative Pour plus d'informations sur les erreurs à réessayer et celles qui sont réessayées par les SDK, consultez le guide de conception. Pour les comptes configurés avec plusieurs régions, il existe certains scénarios où le SDK réessaye automatiquement dans d’autres régions. Pour plus d’informations sur l’implémentation spécifique de .NET, consultez le référentiel source du SDK.
Mise en cache des noms de base de données/collection Récupérez les noms de vos bases de données et de vos conteneurs à partir de la configuration ou mettez-les en cache au démarrage. Les appels tels que ReadDatabaseAsync ou ReadDocumentCollectionAsync et CreateDatabaseQuery ou CreateDocumentCollectionQuery peuvent entraîner des appels de métadonnées au service, qui consomment les RU réservées au système. CreateIfNotExist doit également être utilisé une seule fois pour configurer la base de données. De manière générale, ces opérations ne doivent pas être effectuées fréquemment.
Prise en charge en bloc Dans les scénarios où vous n’avez pas besoin d’optimiser la latence, nous vous recommandons d’activer la Prise en charge en bloc pour vider de gros volumes de données.
Requêtes parallèles Le kit SDK Azure Cosmos DB prend en charge l’exécution de requêtes en parallèle pour améliorer la latence et le débit sur vos requêtes. Nous vous recommandons de définir la MaxConcurrency propriété dans le QueryRequestsOptions au nombre de partitions que vous avez. Si vous ne connaissez pas le nombre de partitions, commencez par utiliser int.MaxValue, ce qui vous donnera la meilleure latence. Réduisez ensuite le nombre jusqu’à ce qu’il corresponde aux restrictions de ressources de l’environnement afin d’éviter les problèmes d’UC élevés. Définissez aussi MaxBufferedItemCount sur le nombre attendu de résultats retournés pour limiter le nombre de résultats prérécupérés.
Tests de performances - Interruptions Lorsque vous effectuez des tests sur votre application, vous devez implémenter des backoffs à intervalles RetryAfter. Le respect de l’interruption contribue à garantir un temps d’attente minimal entre les tentatives.
Indexation La stratégie d’indexation d’Azure Cosmos DB vous permet également de spécifier les chemins de document à inclure ou exclure lors de l’indexation en utilisant les chemins d’accès d’indexation (IndexingPolicy.IncludedPaths et IndexingPolicy.ExcludedPaths). Veillez à exclure les chemins inutilisés de l’indexation pour accélérer les écritures. Pour plus d'informations sur la création d'index à l'aide du SDK, consultez les conseils de performances .NET SDK v3.
Taille du document Les frais de requête d’une opération donnée sont directement liés à la taille du document. Nous vous recommandons de réduire la taille de vos documents, car les opérations sur les documents volumineux coûtent plus que les opérations sur des documents plus petits.
Augmenter le nombre de threads/tâches Étant donné que les appels à Azure Cosmos DB sont effectués sur le réseau, vous devrez peut-être modifier le degré de concurrence de vos requêtes, afin que l’application cliente attende un temps minimal entre les requêtes. Par exemple, si vous utilisez la Bibliothèque parallèle de tâches .NET, créez dans l’ordre des centaines de tâches de lecture ou d’écriture dans Azure Cosmos DB.
Activation des métriques de requête Pour une journalisation supplémentaire de vos exécutions de requêtes back-end, vous pouvez activer les métriques de requête SQL en utilisant notre kit SDK .NET. Pour plus d'informations sur la collecte des métriques de requête SQL, consultez indicateurs de performance et performances des requêtes.
Journalisation SDK Journalisez les diagnostics du SDK pour des scénarios en attente, tels que des exceptions ou lorsque les requêtes dépassent une latence attendue.
DefaultTraceListener DefaultTraceListener pose des problèmes de performance dans les environnements de production, provoquant des goulots d’étranglement importants au niveau du processeur et des E/S. Vérifiez que vous utilisez les dernières versions du SDK ou supprimez DefaultTraceListener de votre application
Évitez d'utiliser des caractères spéciaux dans les identifiants Certains caractères sont restreints et ne peuvent pas être utilisés dans certains identifiants : '/', '\', '?', '#'. La suggestion générale est de ne pas utiliser de caractères spéciaux dans les identifiants tels que le nom de la base de données, le nom de la collection, l'ID de l'élément ou la clé de partition pour éviter tout comportement inattendu.

Capturer les diagnostics

Toutes les réponses du kit de développement logiciel (SDK) y compris CosmosException possède une propriété Diagnostics. Cette propriété enregistre toutes les informations relatives à la requête unique, notamment en cas de nouvelles tentatives ou d’échecs temporaires.

Les diagnostics sont retournés sous forme de chaîne. La chaîne change avec chaque version, car elle est améliorée pour résoudre les différents scénarios. Avec chaque version du SDK, le formatage de la chaîne comporte des changements cassants. N’analysez pas la chaîne pour éviter les changements cassants. L’exemple de code suivant montre comment lire les journaux de diagnostic à l’aide du kit de développement logiciel (SDK) .NET :

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()
}

Meilleures pratiques pour les connexions HTTP

Le Kit de développement logiciel (SDK) .NET utilise HttpClient pour effectuer des requêtes HTTP, quel que soit le mode de connectivité configuré. En mode direct, HTTP est utilisé pour les opérations de métadonnées, et en mode passerelle, il est utilisé pour les opérations de plan de données et de métadonnées. L’un des principes de base de HttpClient consiste à vérifier que le système HttpClient peut réagir aux changements de DNS sur votre compte en personnalisant la durée de vie de la connexion groupée. Tant que les connexions groupées restent ouvertes, elles ne réagissent pas aux changements de DNS. Ce paramètre force la fermeture périodique des connexions groupées, garantissant ainsi que votre application réagit aux changements de DNS. Nous vous recommandons de personnaliser cette valeur en fonction de votre mode de connectivité et de votre charge de travail pour équilibrer l’impact de la création fréquente de nouvelles connexions sur le niveau de performance, avec la nécessité de réagir aux changements de (disponibilité). Une valeur de 5 minutes constitue un bon début que vous pouvez augmenter en cas d’impact sur le niveau de performance, en particulier pour le mode passerelle.

Vous pouvez injecter votre HttpClient personnalisé via CosmosClientOptions.HttpClientFactory, par exemple :

// 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);

Si vous utilisez l’injection de dépendances .NET, vous pouvez simplifier le processus 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);
});

Meilleures pratiques lors de l’utilisation du mode Passerelle

Augmentez System.Net MaxConnections par hôte lorsque vous utilisez le mode Passerelle. Les requêtes d’Azure Cosmos DB sont effectuées via le protocole HTTPS/REST lorsque vous utilisez le mode passerelle. Elles sont soumises à la limite de connexion par défaut par nom d’hôte ou adresse IP. Vous devrez peut-être définir MaxConnections sur une valeur plus élevée (de 100 à 1 000) afin que la bibliothèque cliente puisse utiliser plusieurs connexions simultanées à Azure Cosmos DB. Dans le kit de développement logiciel (SDK) .NET 1.8.0 et versions ultérieures, la valeur par défaut de ServicePointManager.DefaultConnectionLimit est 50. Pour modifier cette valeur, vous pouvez définir CosmosClientOptions.GatewayModeMaxConnectionLimit sur une valeur supérieure.

Meilleures pratiques pour les charges de travail lourdes en écriture

Pour les charges de travail qui ont des charges utiles de création intensives, attribuez à l’option de requête EnableContentResponseOnWrite la valeur false. Le service ne renvoie plus la ressource créée ou mise à jour au kit de développement logiciel (SDK). Normalement, comme l’application détient l’objet en cours de création, le service n’a pas besoin de le retourner. Les valeurs d’en-tête sont toujours accessibles, comme des frais de requête. La désactivation de la réponse de contenu peut améliorer les performances, car le kit SDK n’a plus besoin d’allouer de la mémoire ni de sérialiser le corps de la réponse. Cela réduit également l’utilisation de la bande passante réseau pour améliorer encore les performances.

Important

Le paramètre EnableContentResponseOnWrite pour false désactivera également la réponse d’une opération de déclencheur.

Meilleures pratiques pour les applications multi-locataires

Les applications qui distribuent l’utilisation sur plusieurs locataires où chaque locataire est représenté par une clé de base de données, de conteneur ou de partition différente au sein du même compte Azure Cosmos DB doivent utiliser une seule instance cliente. Une seule instance cliente peut interagir avec toutes les clés de bases de données, conteneurs et partition au sein d’un compte, et il est recommandé d’utiliser le modèle singleton.

Toutefois, lorsque chaque locataire est représenté par un compte Azure Cosmos DB différent, il est nécessaire de créer une instance cliente distincte par compte. Le modèle singleton s’applique toujours à chaque client (un client pour chaque compte pendant la durée de vie de l’application), mais si le volume de locataires est élevé, le nombre de clients peut être difficile à gérer. Les connexions peuvent dépasser les limites de l’environnement de calcul et provoquer des problèmes de connectivité.

Dans ces cas, il est recommandé de :

  • Comprendre les limitations de l’environnement de calcul (ressources de processeur et de connexion). Nous vous recommandons d’utiliser des machines virtuelles avec au moins 4 cœurs et 8 Go de mémoire dans la mesure du possible.
  • En fonction des limitations de l’environnement de calcul, déterminez le nombre d’instances clientes (et donc le nombre de locataires) qu’une seule instance de calcul peut gérer. Vous pouvez estimer le nombre de connexions qui seront ouvertes par client en fonction du mode de connexion choisi.
  • Évaluez la distribution des locataires entre les instances. Si chaque instance de calcul peut gérer correctement un certain nombre limité de locataires, l’équilibrage de charge et le routage des locataires vers différentes instances de calcul permettent une mise à l’échelle à mesure que le nombre de locataires augmente.
  • Pour les charges de travail éparses, envisagez d’utiliser un cache le moins fréquemment utilisé comme structure pour stocker les instances clientes et supprimer les clients pour les locataires qui ne les ont pas consultés dans une fenêtre de temps. L’une des options de .NET est MemoryCacheEntryOptions, où RegisterPostEvictionCallback peut être utilisé pour supprimer les clients inactifs et SetSlidingExpiration pour définir la durée maximale de conservation des connexions inactives.
  • Évaluez l’utilisation du mode passerelle pour réduire le nombre de connexions réseau.
  • Lorsque vous utilisez le mode direct, envisagez d’ajuster CosmosClientOptions.IdleTcpConnectionTimeout et CosmosClientOptions.PortReuseMode sur la configuration du mode direct pour fermer les connexions inutilisées et garder le contrôle du volume de connexions.

Étapes suivantes

Pour obtenir un exemple d’application permettant d’évaluer Azure Cosmos DB lors de scénarios hautes performances sur quelques ordinateurs clients, consultez Test des performances et de la mise à l’échelle avec Azure Cosmos DB.

Pour en savoir plus sur la conception de votre application pour une mise à l’échelle et de hautes performances, consultez Partitionnement, clés de partition et mise à l’échelle dans Cosmos DB.

Vous tentez d’effectuer une planification de la capacité pour une migration vers Azure Cosmos DB ? Vous pouvez utiliser les informations sur votre cluster de bases de données existant pour la planification de la capacité.