Melhores práticas para o SDK .NET do Azure Cosmos DB

APLICA-SE A: NoSQL

Este artigo explica as melhores práticas para utilizar o SDK .NET do Azure Cosmos DB. Ao seguir estas práticas, irá ajudar a melhorar a latência, a disponibilidade e a aumentar o desempenho geral.

Veja o vídeo abaixo para saber mais sobre como utilizar o SDK .NET de um engenheiro do Azure Cosmos DB!

Lista de Verificação

Marcado Assunto Detalhes/Ligações
Versão do SDK Utilizar sempre a versão mais recente do SDK do Azure Cosmos DB disponível para um desempenho ideal.
Cliente Singleton Utilize uma única instância de CosmosClient para a duração da sua aplicação para um melhor desempenho.
Regiões Certifique-se de que executa a aplicação na mesma região do Azure que a sua conta do Azure Cosmos DB, sempre que possível, para reduzir a latência. Ative 2 a 4 regiões e replique as suas contas em várias regiões para obter a melhor disponibilidade. Para cargas de trabalho de produção, ative a ativação pós-falha gerida pelo serviço. Na ausência desta configuração, a conta sofrerá uma perda de disponibilidade de escrita durante toda a duração da indisponibilidade da região de escrita, uma vez que a ativação pós-falha manual não terá êxito devido à falta de conectividade de região. Para saber como adicionar várias regiões com o SDK .NET, visite aqui
Disponibilidade e Ativações Pós-falha Defina ApplicationPreferredRegions ou ApplicationRegion no SDK v3 e PreferredLocations no SDK v2 com a lista de regiões preferenciais. Durante as ativações pós-falha, as operações de escrita são enviadas para a região de escrita atual e todas as leituras são enviadas para a primeira região na sua lista de regiões preferidas. Para obter mais informações sobre a mecânica de ativação pós-falha regional, veja o guia de resolução de problemas de disponibilidade.
CPU Pode deparar-se com problemas de conectividade/disponibilidade devido à falta de recursos no computador cliente. Monitorize a utilização da CPU nos nós que executam o cliente do Azure Cosmos DB e aumente/aumente verticalmente se a utilização for elevada.
Alojamento Utilize o processamento de anfitriões de 64 bits do Windows para obter o melhor desempenho, sempre que possível. Para cargas de trabalho de produção sensíveis à latência do modo direto, recomendamos vivamente a utilização de, pelo menos, 4 núcleos e VMs de memória de 8 GB sempre que possível.
Modos de Conectividade Utilize o modo Direto para obter o melhor desempenho. Para obter instruções sobre como fazê-lo, veja a documentação do SDK V3 ou a documentação do SDK V2.
Rede Se estiver a utilizar uma máquina virtual para executar a sua aplicação, ative a Rede Acelerada na VM para ajudar com estrangulamentos devido a tráfego elevado e reduzir a latência ou a instabilidade da CPU. Também poderá considerar a utilização de uma Máquina Virtual de extremidade superior, em que a utilização máxima da CPU é inferior a 70%.
Esgotamento de Portas Efémeras Para ligações dispersas ou esporádicas, definimos o IdleConnectionTimeout e PortReuseMode como PrivatePortPool. A IdleConnectionTimeout propriedade ajuda a controlar o tempo após o qual as ligações não utilizadas são fechadas. Isto reduz o número de ligações não utilizadas. Por predefinição, as ligações inativas são mantidas abertas indefinidamente. O conjunto de valores tem de ser maior ou igual a 10 minutos. Recomendamos valores entre 20 minutos e 24 horas. A PortReuseMode propriedade permite que o SDK utilize um pequeno conjunto de portas efémeras para vários pontos finais de destino do Azure Cosmos DB.
Utilizar Assíncrono/Aguardar Evite bloquear chamadas: Task.Result, Task.Waite Task.GetAwaiter().GetResult(). Toda a pilha de chamadas é assíncrona para beneficiar de padrões assíncronos/de espera . Muitas chamadas de bloqueio síncronas levam à desconexão do Conjunto de Threads e a tempos de resposta degradados.
Tempos Limite Ponto a Ponto Para obter tempos limite ponto a ponto, tem de utilizar parâmetros RequestTimeout e CancellationToken . Para obter mais detalhes , visite o nosso guia de resolução de problemas de tempo limite.
Repetir Lógica Para obter mais informações sobre os erros a repetir e quais são repetidos pelos SDKs, veja o guia de estrutura. Para contas configuradas com várias regiões, existem alguns cenários em que o SDK tentará novamente automaticamente noutras regiões. Para obter detalhes de implementação específicos do .NET, visite o repositório de origem do SDK.
Colocação em cache de nomes de bases de dados/coleções Obtenha os nomes das bases de dados e dos contentores a partir da configuração ou coloque-os em cache no início. Chamadas como ReadDatabaseAsync ou ReadDocumentCollectionAsync e CreateDatabaseQuery ou CreateDocumentCollectionQuery resultarão em chamadas de metadados para o serviço, que consomem do limite de RUs reservadas pelo sistema. CreateIfNotExist também deve ser utilizado apenas uma vez para configurar a base de dados. No geral, estas operações devem ser executadas com pouca frequência.
Suporte em Massa Em cenários em que poderá não precisar de otimizar para latência, recomendamos que ative o Suporte em massa para a captura de grandes volumes de dados.
Consultas Paralelas O SDK do Azure Cosmos DB suporta a execução de consultas em paralelo para uma melhor latência e débito nas suas consultas. Recomendamos que defina a MaxConcurrency propriedade dentro do QueryRequestsOptions para o número de partições que tem. Se não tiver conhecimento do número de partições, comece por utilizar int.MaxValue, o que lhe dará a melhor latência. Em seguida, diminua o número até que se ajuste às restrições de recursos do ambiente para evitar problemas de CPU elevados. Além disso, defina o MaxBufferedItemCount para o número esperado de resultados devolvidos para limitar o número de resultados pré-correspondentes.
Backoffs de Testes de Desempenho Ao efetuar testes na sua aplicação, deve implementar backoffs em RetryAfter intervalos. Respeitar o backoff ajuda a garantir que passa um período mínimo de tempo à espera entre repetições.
Indexação A política de indexação do Azure Cosmos DB também lhe permite especificar que caminhos de documento incluir ou excluir da indexação através de caminhos de indexação (IndexingPolicy.IncludedPaths e IndexingPolicy.ExcludedPaths). Certifique-se de que exclui os caminhos não utilizados da indexação para escritas mais rápidas. Para obter mais informações sobre como criar índices com o SDK, veja sugestões de desempenho do SDK .NET v3.
Tamanho do Documento O custo do pedido de uma operação especificada está diretamente correlacionado com o tamanho do documento. Recomendamos que reduza o tamanho dos seus documentos, uma vez que as operações em documentos grandes custam mais do que as operações em documentos mais pequenos.
Aumentar o número de threads/tarefas Uma vez que as chamadas para o Azure Cosmos DB são efetuadas através da rede, poderá ter de variar o grau de simultaneidade dos seus pedidos para que a aplicação cliente passe um tempo mínimo à espera entre pedidos. Por exemplo, se estiver a utilizar a Biblioteca Paralela de Tarefas .NET, crie na ordem de centenas de tarefas que leem ou escrevem no Azure Cosmos DB.
Ativar Métricas de Consulta Para obter mais registos das execuções de consultas de back-end, pode ativar as Métricas de Consulta SQL com o nosso SDK .NET. Para obter mais informações sobre como recolher Métricas de Consulta SQL, veja métricas de consulta e desempenho.
Registo do SDK Diagnósticos do SDK de registo para cenários pendentes, como exceções ou quando os pedidos vão além de uma latência esperada.
DefaultTraceListener O DefaultTraceListener coloca problemas de desempenho em ambientes de produção que causam estrangulamentos elevados de CPU e E/S. Certifique-se de que está a utilizar as versões mais recentes do SDK ou remova o DefaultTraceListener da sua aplicação
Evite utilizar carateres especiais em identificadores Alguns carateres são restritos e não podem ser utilizados em alguns identificadores: '/', '\', '?', '#'. A recomendação geral é não utilizar carateres especiais em identificadores como o nome da base de dados, o nome da coleção, o ID do item ou a chave de partição para evitar qualquer comportamento inesperado.

Capturar diagnósticos

Todas as respostas no SDK, incluindo CosmosException, têm uma Diagnostics propriedade. Esta propriedade regista todas as informações relacionadas com o pedido único, incluindo se houve repetições ou falhas transitórias.

Os diagnósticos são devolvidos como uma cadeia. A cadeia muda com cada versão, uma vez que é melhorada para a resolução de problemas de diferentes cenários. Com cada versão do SDK, a cadeia terá alterações interruptivas à formatação. Não analise a cadeia para evitar alterações interruptivas. O seguinte exemplo de código mostra como ler registos de diagnóstico com o 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()
}

Melhores práticas para ligações HTTP

O SDK .NET utiliza HttpClient para efetuar pedidos HTTP, independentemente do modo de conectividade configurado. No modo Direto , HTTP é utilizado para operações de metadados e no modo de Gateway é utilizado para operações de plano de dados e metadados. Uma das noções básicas do HttpClient é certificar-se de que consegue HttpClient reagir às alterações de DNS na sua conta ao personalizar a duração da ligação de conjunto. Desde que as ligações de conjunto sejam mantidas abertas, não reagem às alterações de DNS. Esta definição força o encerramento periódico das ligações agrupadas, garantindo que a sua aplicação reage a alterações de DNS. A nossa recomendação é que personalize este valor de acordo com o modo de conectividade e a carga de trabalho para equilibrar o impacto no desempenho da criação frequente de novas ligações, com a necessidade de reagir a alterações de DNS (disponibilidade). Um valor de 5 minutos seria um bom começo que pode ser aumentado se estiver a afetar o desempenho, especialmente no modo de Gateway.

Pode injetar o httpClient personalizado através CosmosClientOptions.HttpClientFactoryde , por exemplo:

// 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 utilizar a injeção de dependência .NET, pode simplificar o 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);
});

Melhores práticas ao utilizar o modo de Gateway

Aumente System.Net MaxConnections por anfitrião quando utiliza o Modo de gateway. Os pedidos do Azure Cosmos DB são feitos através de HTTPS/REST quando utiliza o Modo de gateway. Estão sujeitos ao limite de ligação predefinido por nome de anfitrião ou endereço IP. Poderá ter de definir MaxConnections para um valor mais alto (de 100 a 1000) para que a biblioteca de cliente possa utilizar várias ligações simultâneas ao Azure Cosmos DB. No SDK .NET 1.8.0 e posterior, o valor predefinido para ServicePointManager.DefaultConnectionLimit é 50. Para alterar o valor, pode definir CosmosClientOptions.GatewayModeMaxConnectionLimit para um valor mais alto.

Melhores práticas para cargas de trabalho com escrita intensiva

Para cargas de trabalho com payloads de criação pesados, defina a opção EnableContentResponseOnWrite de pedido como false. O serviço deixará de devolver o recurso criado ou atualizado ao SDK. Normalmente, como a aplicação tem o objeto que está a ser criado, não precisa que o serviço o devolva. Os valores dos cabeçalhos ainda estão acessíveis, como um custo de pedido. Desativar a resposta de conteúdo pode ajudar a melhorar o desempenho, porque o SDK já não precisa de alocar memória ou serializar o corpo da resposta. Também reduz a utilização da largura de banda de rede para ajudar ainda mais o desempenho.

Importante

Definir EnableContentResponseOnWrite como false também desativará a resposta de uma operação de acionador.

Melhores práticas para aplicações multi-inquilino

As aplicações que distribuem a utilização por vários inquilinos em que cada inquilino é representado por uma base de dados, contentor ou chave de partição diferente na mesma conta do Azure Cosmos DB devem utilizar uma única instância de cliente. Uma única instância de cliente pode interagir com todas as bases de dados, contentores e chaves de partição numa conta e é melhor prática utilizar o padrão singleton.

No entanto, quando cada inquilino é representado por uma conta do Azure Cosmos DB diferente, é necessário criar uma instância de cliente separada por conta. O padrão singleton ainda se aplica a cada cliente (um cliente para cada conta durante a duração da aplicação), mas se o volume de inquilinos for elevado, o número de clientes pode ser difícil de gerir. As ligações podem aumentar para além dos limites do ambiente de computação e causar problemas de conectividade.

Nestes casos, é recomendado:

  • Compreender as limitações do ambiente de computação (CPU e recursos de ligação). Recomendamos a utilização de VMs com, pelo menos, 4 núcleos e 8 GB de memória sempre que possível.
  • Com base nas limitações do ambiente de computação, determine o número de instâncias de cliente (e, portanto, o número de inquilinos) que uma única instância de computação pode processar. Pode estimar o número de ligações que serão abertas por cliente consoante o modo de ligação escolhido.
  • Avaliar a distribuição de inquilinos entre instâncias. Se cada instância de computação conseguir processar com êxito uma determinada quantidade limitada de inquilinos, o balanceamento de carga e o encaminhamento de inquilinos para diferentes instâncias de computação permitirão o dimensionamento à medida que o número de inquilinos aumenta.
  • Para cargas de trabalho dispersas, considere utilizar uma cache Menos Frequentemente Utilizada como a estrutura para armazenar as instâncias de cliente e eliminar clientes para inquilinos que não tenham sido acedidos dentro de um período de tempo. Uma opção no .NET é MemoryCacheEntryOptions, em que RegisterPostEvictionCallback pode ser utilizado para eliminar clientes inativos e SetSlidingExpiration pode ser utilizado para definir o tempo máximo para manter ligações inativas.
  • Avalie com o Modo de gateway para reduzir o número de ligações de rede.
  • Ao utilizar o Modo direto , considere ajustar CosmosClientOptions.IdleTcpConnectionTimeout e CosmosClientOptions.PortReuseMode na configuração do modo direto para fechar as ligações não utilizadas e manter o volume de ligações sob controlo.

Passos seguintes

Para uma aplicação de exemplo que é utilizada para avaliar o Azure Cosmos DB para cenários de elevado desempenho em alguns computadores cliente, veja Desempenho e teste de dimensionamento com o Azure Cosmos DB.

Para saber mais sobre como conceber a sua aplicação para dimensionamento e elevado desempenho, veja Criação de partições e dimensionamento no Azure Cosmos DB.

Está a tentar planear a capacidade de uma migração para o Azure Cosmos DB? Pode utilizar informações sobre o cluster de bases de dados existentes para o planeamento de capacidade.