Práticas recomendadas para o Azure Cosmos DB .NET SDK
APLICA-SE A: NoSQL
Este artigo apresenta as práticas recomendadas para usar o SDK .NET do Azure Cosmos DB. Seguir essas práticas ajudará a melhorar sua latência, disponibilidade e aumentar o desempenho geral.
Assista ao vídeo abaixo para saber mais sobre como usar o SDK do .NET de um engenheiro do Azure Cosmos DB!
Lista de Verificação
Selecionado | Assunto | Detalhes/Links |
---|---|---|
Versão do SDK | Sempre usando a versão mais recente do SDK do Azure Cosmos DB disponível para um desempenho ideal. | |
Cliente Singleton | Use uma única instância do CosmosClient durante o tempo de vida do seu aplicativo para obter um melhor desempenho. |
|
Regiões | Certifique-se de executar seu aplicativo na mesma região do Azure que sua conta do Azure Cosmos DB, sempre que possível para reduzir a latência. Habilite de 2 a 4 regiões e replique suas contas em várias regiões para obter a melhor disponibilidade. Para cargas de trabalho de produção, habilite o failover gerenciado pelo serviço. Na ausência dessa configuração, a conta sofrerá perda de disponibilidade de gravação durante toda a duração da interrupção da região de gravação, pois o failover manual não terá êxito devido à falta de conectividade da região. Para saber como adicionar várias regiões usando o SDK do .NET, visite aqui | |
Disponibilidade e failovers | Defina ApplicationPreferredRegions ou ApplicationRegion no SDK v3 e PreferredLocations no SDK v2 usando a lista de regiões preferenciais. Durante os failovers, as operações de gravação são enviadas para a região de gravação atual e todas as leituras são enviadas para a primeira região da sua lista de regiões preferidas. Para obter mais informações sobre a mecânica de failover regional, consulte o guia de solução de problemas de disponibilidade. | |
CPU | Você pode ter problemas de conectividade/disponibilidade devido à falta de recursos na máquina cliente. Monitore a utilização da CPU em nós que executam o cliente do Azure Cosmos DB e aumente ou diminua a escala se o uso for alto. | |
Alojamento | Use o processamento de host do Windows de 64 bits para obter o melhor desempenho, sempre que possível. Para cargas de trabalho de produção sensíveis à latência do modo direto, é altamente recomendável usar pelo menos VMs de memória de 4 núcleos e 8 GB sempre que possível. | |
Modos de conectividade | Use o modo Direto para obter o melhor desempenho. Para obter instruções sobre como fazer isso, consulte a documentação do SDK V3 ou a documentação do SDK V2. | |
Rede | Se estiver usando uma máquina virtual para executar seu aplicativo, habilite a Rede Acelerada em sua VM para ajudar com gargalos devido ao alto tráfego e reduzir a latência ou o desvio da CPU. Você também pode considerar o uso de uma máquina virtual mais avançada onde o uso máximo da CPU é inferior a 70%. | |
Exaustão Efémera do Porto | Para conexões esparsas ou esporádicas, definimos o IdleConnectionTimeout e PortReuseMode para PrivatePortPool . A IdleConnectionTimeout propriedade ajuda a controlar o tempo após o qual as conexões não utilizadas são fechadas. Isso reduz o número de conexões não utilizadas. Por padrão, as conexões ociosas são mantidas abertas indefinidamente. O valor definido deve ser maior ou igual a 10 minutos. Foram recomendados valores entre 20 minutos e 24 horas. A PortReuseMode propriedade permite que o SDK use um pequeno pool de portas efêmeras para vários pontos de extremidade de destino do Azure Cosmos DB. |
|
Usar Async/Await | Evite bloquear chamadas: Task.Result , Task.Wait e Task.GetAwaiter().GetResult() . Toda a pilha de chamadas é assíncrona para se beneficiar dos padrões async /await . Muitas chamadas de bloqueio síncronas levam à inanição do pool de threads e a tempos de resposta degradados. |
|
Tempos limite de ponta a ponta | Para obter tempos limite de ponta a ponta, você precisa usar ambos os RequestTimeout parâmetros e CancellationToken . Para obter mais detalhes , visite nosso guia de solução de problemas de tempo limite. |
|
Repetir a Lógica | Para obter mais informações sobre quais erros devem ser repetidos e quais são repetidos pelos SDKs, consulte o guia de design. Para contas configuradas com várias regiões, há alguns cenários em que o SDK repetirá automaticamente em outras regiões. Para obter detalhes de implementação específicos do .NET, visite o repositório de origem do SDK. | |
Armazenamento em cache de nomes de banco de dados/coleção | Recupere os nomes de seus bancos de dados e contêineres da configuração ou armazene-os em cache na inicialização. Chamadas como ReadDatabaseAsync ou ReadDocumentCollectionAsync e CreateDatabaseQuery ou CreateDocumentCollectionQuery resultarão em chamadas de metadados para o serviço, que consomem a partir do limite de RU reservado pelo sistema. CreateIfNotExist também só deve ser usado uma vez para configurar o banco de dados. De um modo geral, estas operações devem ser realizadas com pouca frequência. |
|
Suporte em massa | Em cenários em que talvez não seja necessário otimizar a latência, recomendamos habilitar o suporte em massa para despejar grandes volumes de dados. | |
Consultas paralelas | O SDK do Azure Cosmos DB dá suporte à execução de consultas em paralelo para melhor latência e taxa de transferência em suas consultas. Recomendamos definir a MaxConcurrency propriedade dentro do QueryRequestsOptions para o número de partições que você tem. Se você não está ciente do número de partições, comece usando int.MaxValue , que lhe dará a melhor latência. Em seguida, diminua o número até que ele se ajuste às restrições de recursos do ambiente para evitar problemas de CPU altos. Além disso, defina o MaxBufferedItemCount número esperado de resultados retornados para limitar o número de resultados pré-buscados. |
|
Backoffs de testes de desempenho | Ao executar testes em seu aplicativo, você deve implementar backoffs em RetryAfter intervalos. Respeitar o backoff ajuda a garantir que você passe uma quantidade mínima de tempo esperando entre as tentativas. |
|
Indexação | A política de indexação do Azure Cosmos DB também permite especificar quais caminhos de documento devem ser incluídos ou excluídos da indexação usando caminhos de indexação (IndexingPolicy.IncludedPaths e IndexingPolicy.ExcludedPaths). Certifique-se de excluir caminhos não utilizados da indexação para gravações mais rápidas. Para obter mais informações sobre como criar índices usando o SDK, consulte dicas de desempenho .NET SDK v3. | |
Tamanho do documento | A cobrança de solicitação de uma operação especificada está diretamente correlacionada ao tamanho do documento. Recomendamos reduzir o tamanho de seus documentos, pois as operações em documentos grandes custam mais do que as operações em documentos menores. | |
Aumentar o número de threads/tarefas | Como as chamadas para o Azure Cosmos DB são feitas pela rede, talvez seja necessário variar o grau de simultaneidade de suas solicitações para que o aplicativo cliente passe o mínimo de tempo esperando entre as solicitações. Por exemplo, se você estiver usando a Biblioteca Paralela de Tarefas do .NET, crie na ordem de centenas de tarefas que leem ou gravam no Azure Cosmos DB. | |
Habilitando métricas de consulta | Para obter mais registro em log de suas execuções de consulta de back-end, você pode habilitar as métricas de consulta SQL usando nosso SDK do .NET. Para obter mais informações sobre como coletar métricas de consulta SQL, consulte métricas de consulta e desempenho. | |
Registro em log do SDK | Registre o diagnóstico do SDK para cenários pendentes, como exceções ou quando as solicitações ultrapassam uma latência esperada. | |
DefaultTraceListener | O DefaultTraceListener apresenta problemas de desempenho em ambientes de produção, causando altos gargalos de CPU e E/S. Verifique se você está usando as versões mais recentes do SDK ou remova o DefaultTraceListener do seu aplicativo | |
Evite usar caracteres especiais em identificadores | Alguns caracteres são restritos e não podem ser usados em alguns identificadores: '/', '\', '?', '#'. A recomendação geral é não usar caracteres especiais em identificadores como nome do banco de dados, nome da coleção, ID do item ou chave de partição para evitar qualquer comportamento inesperado. |
Capturar diagnósticos
Todas as respostas no SDK, incluindo CosmosException
, têm uma Diagnostics
propriedade. Essa propriedade registra todas as informações relacionadas à solicitação única, incluindo se houve novas tentativas ou falhas transitórias.
Os diagnósticos são retornados como uma cadeia de caracteres. A cadeia de caracteres muda a cada versão, pois é aprimorada para solucionar problemas de diferentes cenários. Com cada versão do SDK, a cadeia de caracteres terá alterações de quebra na formatação. Não analise a cadeia de caracteres para evitar a quebra de alterações. O exemplo de código a seguir mostra como ler logs de diagnóstico usando o SDK do .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()
}
Práticas recomendadas para conexões HTTP
O SDK do .NET usa HttpClient
para executar solicitações HTTP independentemente do modo de conectividade configurado. No modo Direto, o HTTP é usado para operações de metadados e no modo Gateway é usado para operações de plano de dados e metadados. Um dos fundamentos do HttpClient é certificar-se de que o HttpClient
pode reagir às alterações de DNS em sua conta, personalizando o tempo de vida da conexão em pool. Desde que as conexões em pool sejam mantidas abertas, elas não reagem às alterações de DNS. Essa configuração força as conexões agrupadas a serem fechadas periodicamente, garantindo que seu aplicativo reaja às alterações de DNS. Nossa recomendação é que você personalize esse valor de acordo com seu modo de conectividade e carga de trabalho para equilibrar o impacto no desempenho da criação frequente de novas conexõ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 afetando o desempenho, especialmente para o modo Gateway.
Você pode injetar seu HttpClient personalizado através de CosmosClientOptions.HttpClientFactory
, 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 você usar a injeção de dependência do .NET, poderá 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);
});
Práticas recomendadas ao usar o modo Gateway
Aumente System.Net MaxConnections
por host quando você usa o modo Gateway. As solicitações do Azure Cosmos DB são feitas por HTTPS/REST quando você usa o modo Gateway. Eles estão sujeitos ao limite de conexão padrão por nome de host ou endereço IP. Talvez seja necessário definir MaxConnections
como um valor mais alto (de 100 a 1.000) para que a biblioteca de cliente possa usar várias conexões simultâneas com o Azure Cosmos DB. No .NET SDK 1.8.0 e posterior, o valor padrão para ServicePointManager.DefaultConnectionLimit
é 50. Para alterar o valor, você pode definir CosmosClientOptions.GatewayModeMaxConnectionLimit
como um valor mais alto.
Práticas recomendadas para cargas de trabalho com muita gravação
Para cargas de trabalho com cargas úteis de criação pesadas, defina a EnableContentResponseOnWrite
opção de solicitação como false
. O serviço não retornará mais o recurso criado ou atualizado para o SDK. Normalmente, como o aplicativo tem o objeto que está sendo criado, ele não precisa do serviço para retorná-lo. Os valores de cabeçalho ainda estão acessíveis, como uma taxa de solicitação. Desabilitar a resposta de conteúdo pode ajudar a melhorar o desempenho, porque o SDK não precisa mais alocar memória ou serializar o corpo da resposta. Ele também reduz o uso da largura de banda da rede para ajudar ainda mais o desempenho.
Importante
A configuração EnableContentResponseOnWrite
como false
também desativará a resposta de uma operação de gatilho.
Práticas recomendadas para aplicativos multilocatários
Os aplicativos que distribuem o uso entre vários locatários em que cada locatário é representado por um banco de dados, contêiner ou chave de partição diferente dentro da mesma conta do Azure Cosmos DB devem usar uma única instância de cliente. Uma única instância de cliente pode interagir com todos os bancos de dados, contêineres e chaves de partição dentro de uma conta, e é uma prática recomendada usar o padrão singleton.
No entanto, quando cada locatário é representado por uma conta diferente do Azure Cosmos DB, é 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 o tempo de vida do aplicativo), mas se o volume de locatários for alto, o número de clientes pode ser difícil de gerenciar. As conexões podem aumentar além dos limites do ambiente de computação e causar problemas de conectividade.
Recomenda-se, nestes casos:
- Compreender as limitações do ambiente de computação (recursos de CPU e conexão). Recomendamos o uso 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 locatários) que uma única instância de computação pode manipular. Você pode estimar o número de conexões que serão abertas por cliente, dependendo do modo de conexão escolhido.
- Avalie a distribuição de locatários entre instâncias. Se cada instância de computação puder lidar com êxito com uma determinada quantidade limitada de locatários, o balanceamento de carga e o roteamento de locatários para instâncias de computação diferentes permitirão o dimensionamento à medida que o número de locatários crescer.
- Para cargas de trabalho esparsas, considere o uso de um cache usado com menos frequência como a estrutura para armazenar as instâncias do cliente e descartar clientes para locatários que não foram acessados dentro de uma janela de tempo. Uma opção no .NET é MemoryCacheEntryOptions, onde RegisterPostEvictionCallback pode ser usado para descartar clientes inativos e SetSlidingExpiration pode ser usado para definir o tempo máximo para manter conexões inativas.
- Avalie o uso do modo Gateway para reduzir o número de conexões de rede.
- Ao usar o modo Direto, considere ajustar CosmosClientOptions.IdleTcpConnectionTimeout e CosmosClientOptions.PortReuseMode na configuração do modo direto para fechar conexões não utilizadas e manter o volume de conexões sob controle.
Próximos passos
Para obter um aplicativo de exemplo usado para avaliar o Azure Cosmos DB para cenários de alto desempenho em algumas máquinas cliente, consulte Testes de desempenho e dimensionamento com o Azure Cosmos DB.
Para saber mais sobre como projetar seu aplicativo para dimensionamento e alto desempenho, consulte Particionamento e dimensionamento no Azure Cosmos DB.
Tentando fazer o planejamento de capacidade para uma migração para o Azure Cosmos DB? Você pode usar informações sobre seu cluster de banco de dados existente para planejamento de capacidade.
- Se você souber as taxas de solicitação típicas para sua carga de trabalho de banco de dados atual, leia sobre como estimar unidades de solicitação usando o planejador de capacidade do Azure Cosmos DB