Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Importante
Esse não é o SDK de Java mais recente para Azure Cosmos DB! Você deve atualizar seu projeto para o SDK do Java v4 do Azure Cosmos DB e ler o guia de dicas de desempenho do SDK do Java do Azure Cosmos DB v4. Siga as instruções no guia Migrar para o Azure Cosmos DB Java SDK v4 e no guia Reactor vs RxJava para atualizar.
As dicas de desempenho neste artigo são apenas para o SDK do Azure Cosmos DB para Java Assíncrono v2. Consulte as notas de versão do SDK do Java assíncrono do Azure Cosmos DB v2, o repositório Maven e o guia de solução de problemas do SDK do Java Assíncrono do Azure Cosmos DB v2 para obter mais informações.
Importante
Em 31 de agosto de 2024, o SDK do Java Assíncrono do Azure Cosmos DB v2.x será desativado; o SDK e todos os aplicativos que usam o SDK continuarão funcionando; O Azure Cosmos DB simplesmente deixará de fornecer mais manutenção e suporte para esse SDK. É recomendável seguir as instruções acima para migrar para o SDK do Java do Azure Cosmos DB v4.
O Azure Cosmos DB é um banco de dados distribuído rápido e flexível que pode ser dimensionado perfeitamente com garantia de latência e produtividade. Você não precisa fazer alterações importantes de arquitetura nem escrever um código complexo para dimensionar seu banco de dados com o Azure Cosmos DB. Aumentar e reduzir é tão fácil quanto fazer uma única chamada à API ou uma chamada ao método do SDK. No entanto, como o Azure Cosmos DB é acessado por meio de chamadas de rede, há otimizações do lado do cliente que você pode fazer para atingir o desempenho máximo ao usar o SDK de Java Assíncrono do Azure Cosmos DB v2.
Assim, se você estiver se perguntando "Como posso melhorar o desempenho do meu banco de dados?", considere as seguintes opções:
Rede
Modo de conexão: usar o modo Direto
Como um cliente se conecta ao Azure Cosmos DB tem implicações importantes no desempenho, especialmente em termos de latência do lado do cliente. O ConnectionMode é uma configuração de chave disponível para configurar o ConnectionPolicy do cliente. Para a versão 2 do SDK Assíncrono de Java do Azure Cosmos DB, os dois modos de conexão disponíveis são:
O modo de gateway tem suporte em todas as plataformas do SDK e é a opção configurada por padrão. Se seus aplicativos forem executados em uma rede corporativa com restrições estritas de firewall, o modo de gateway será a melhor opção, pois ele usa a porta HTTPS padrão e um único ponto de extremidade. A compensação de desempenho, no entanto, é que o modo gateway envolve um salto de rede adicional sempre que os dados são lidos ou gravados no Azure Azure Cosmos DB. Por isso, o modo Direto oferece melhor desempenho devido a menos saltos de rede.
O ConnectionMode é configurado durante a construção da instância do DocumentClient com o parâmetro ConnectionPolicy .
SDK do Java Assíncrono V2 (Maven com.microsoft.azure::azure-cosmosdb)
public ConnectionPolicy getConnectionPolicy() {
ConnectionPolicy policy = new ConnectionPolicy();
policy.setConnectionMode(ConnectionMode.Direct);
policy.setMaxPoolSize(1000);
return policy;
}
ConnectionPolicy connectionPolicy = new ConnectionPolicy();
DocumentClient client = new DocumentClient(HOST, MASTER_KEY, connectionPolicy, null);
Colocar os clientes na mesma região do Azure para o desempenho
Quando possível, coloque aplicativos que chamam o Azure Cosmos DB na mesma região do banco de dados do Azure Cosmos DB. Para uma comparação aproximada, as chamadas para o Azure Cosmos DB na mesma região são concluídas de 1 a 2 ms, mas a latência entre a Costa Leste e a Oeste dos EUA é maior que >50 ms. Provavelmente, essa latência pode variar entre as solicitações dependendo da rota seguida pela solicitação conforme ela passa do cliente para o limite de datacenter do Azure. A menor latência possível é alcançada garantindo que o aplicativo de chamada está localizado na mesma região do Azure do ponto de extremidade do Azure Cosmos DB provisionado. Para obter uma lista de regiões disponíveis, consulte Regiões do Azure.
Uso do SDK
Instalar o SDK mais recente
Os SDKs do Azure Cosmos DB estão constantemente sendo aprimorados para fornecer o melhor desempenho. Consulte as páginas de Notas de Versão do SDK Java assíncrono do Azure Cosmos DB v2 para determinar o SDK mais recente e verificar as melhorias.
Usar um cliente do Azure Cosmos DB singleton para obter o tempo de vida do aplicativo
Cada instância de AsyncDocumentClient é segura para threads e executa um gerenciamento de conexão eficiente e cache de endereços. Para permitir um gerenciamento de conexão eficiente e um melhor desempenho por AsyncDocumentClient, é recomendável usar uma única instância de AsyncDocumentClient por AppDomain durante o tempo de vida do aplicativo.
Ajustando a Política de Conexão
Por padrão, as solicitações do Azure Cosmos DB no modo Direto são feitas por TCP ao usar o SDK de Java Assíncrono do Azure Cosmos DB v2. Internamente, o SDK usa uma arquitetura especial do modo Direto para gerenciar dinamicamente os recursos de rede e obter o melhor desempenho.
No SDK Java Assíncrono do Azure Cosmos DB v2, o modo Direto é a opção ideal para aumentar o desempenho do banco de dados com a maioria das cargas de trabalho.
- Visão geral do modo Direto
A arquitetura do lado do cliente empregada no modo Direto permite a utilização previsível da rede e o acesso multiplexado às réplicas do Azure Cosmos DB. O diagrama acima mostra como o modo Direto roteia solicitações de cliente para réplicas no back-end do Azure Cosmos DB. A arquitetura de modo direto aloca até 10 canais no lado do cliente por réplica de BD. Um Canal é uma conexão TCP precedida por um buffer de solicitação, que comporta 30 solicitações. Os canais pertencentes a uma réplica são alocados dinamicamente conforme necessário pelo endpoint de serviço da réplica. Quando o usuário emite uma solicitação no modo Direto, o TransportClient encaminha a solicitação para o ponto de extremidade de serviço adequado com base na chave de partição. A Fila de Solicitação armazena as solicitações antes do Ponto de Extremidade de Serviço.
Opções de Configuração do ConnectionPolicy para o modo Direto
Como primeira etapa, use as seguintes configurações recomendadas abaixo. Entre em contato com a equipe do Azure Cosmos DB se você tiver problemas neste tópico específico.
Se você estiver usando o Azure Cosmos DB como um banco de dados de referência (ou seja, o banco de dados é usado para muitas operações de leitura de ponto e poucas operações de gravação), pode ser aceitável definir idleEndpointTimeout como 0 (ou seja, sem tempo limite).
Opções de configuração Padrão bufferPageSize 8192 tempoLimiteDeConexão "PT1M" idleChannelTimeout "PT0S" idleEndpointTimeout "PT1M10S" capacidadeMáximaDoBuffer 8388608 maxChannelsPerEndpoint 10 maxRequestsPerChannel (máximo de solicitações por canal) 30 tempoDeDetecçãoDeTravamentoDeRecepção "PT1M5S" requestExpiryInterval "PT5S" requestTimeout "PT1M" SolicitarResoluçãoDoTimer "PT0.5S" sendHangDetectionTime "PT10S" tempoLimiteDesligamento "PT15S"
Dicas de programação para o modo Direto
Revise o artigo de solução de problemas do SDK Java Async do Azure Cosmos DB v2 como base para resolver problemas de SDK.
Algumas dicas de programação importantes ao usar o modo Direto:
Use o multithreading em seu aplicativo para transferência eficiente de dados TCP – depois de fazer uma solicitação, seu aplicativo deve assinar para receber dados em outro thread. Não fazer isso força uma operação "half-duplex" não intencional, e as solicitações subsequentes são bloqueadas enquanto aguardam a resposta da solicitação anterior.
Executar cargas de trabalho com uso intensivo de computação em um thread dedicado – por motivos semelhantes à dica anterior, operações como o processamento de dados complexos são melhor colocadas em um thread separado. Uma solicitação que extrai dados de outro armazenamento de dados (por exemplo, se o thread utiliza armazenamentos de dados do Azure Cosmos DB e do Spark simultaneamente) pode apresentar maior latência e é recomendável gerar um thread adicional que aguarda uma resposta do outro armazenamento de dados.
- A rede IO subjacente no Azure Cosmos DB Async Java SDK v2 é gerenciada pelo Netty. Confira estas dicas para evitar padrões de codificação que bloqueiam threads de E/S do Netty.
Modelagem de dados – o SLA do Azure Cosmos DB pressupõe que o tamanho do documento seja menor que 1 KB. Otimizar seu modelo de dados e programação para favorecer um tamanho de documento menor geralmente levará a uma latência reduzida. Se você precisar de armazenamento e recuperação de documentos maiores que 1 KB, a abordagem recomendada é que os documentos se vinculem a dados no Armazenamento de Blobs do Azure.
Ajustando consultas paralelas para coleções particionadas
O SDK do Java assíncrono do Azure Cosmos DB v2 dá suporte a consultas paralelas, que permitem consultar uma coleção particionada em paralelo. Para obter mais informações, consulte exemplos de código relacionados ao trabalho com os SDKs. As consultas paralelas são projetadas para melhorar a latência e o desempenho de consulta sobre seu equivalente serial.
Ajuste de setMaxDegreeOfParallelism:
As consultas paralelas funcionam consultando várias partições em paralelo. No entanto, os dados de uma coleção particionada individual são buscados em série de acordo com a consulta. Portanto, use setMaxDegreeOfParallelism para definir o número de partições que maximize a chance de alcançar a consulta mais eficiente, desde que todas as outras condições do sistema permaneçam as mesmas. Se você não souber o número de partições, poderá usar setMaxDegreeOfParallelism para definir um número alto e o sistema escolherá o mínimo (número de partições, entrada fornecida pelo usuário) como o grau máximo de paralelismo.
É importante observar que as consultas paralelas produzem os melhores benefícios se os dados forem distribuídos uniformemente em todas as partições em relação à consulta. Se a coleção particionada for particionada de forma que todos ou a maioria dos dados retornados por uma consulta estejam concentrados em algumas partições (uma partição na pior das hipóteses), o desempenho da consulta será gargalado por essas partições.
Ajuste setMaxBufferedItemCount:
A consulta paralela foi projetada para pré-realizar resultados enquanto o lote atual de resultados está sendo processado pelo cliente. A pré-busca ajuda na melhoria geral da latência de uma consulta. setMaxBufferedItemCount limita o número de resultados pré-buscados. Definir setMaxBufferedItemCount como o número esperado de resultados retornados (ou um número maior) permite que a consulta receba o benefício máximo da pré-busca.
A pré-busca funciona da mesma maneira, independentemente do MaxDegreeOfParallelism, e há um único buffer para os dados de todas as partições.
Implementar o retrocesso em intervalos de getRetryAfterInMilliseconds
Durante o teste de desempenho, você deve aumentar a carga até que uma pequena porcentagem de solicitações seja sufocada. Se limitado, o aplicativo cliente deverá recuar para o intervalo de repetição especificado pelo servidor. Respeitar o backoff garante que você passe o mínimo de tempo aguardando entre tentativas.
Escalar horizontalmente sua carga de trabalho do cliente
Se você estiver testando em níveis de alta taxa de transferência (>50.000 RU/s), o aplicativo cliente poderá se tornar o gargalo devido à limitação do computador na utilização da CPU ou da rede. Se você chegar a este ponto, poderá continuar aumentando a conta do Azure Cosmos DB ainda mais distribuindo seus aplicativos cliente entre vários servidores.
Usar endereçamento baseado em nome
Use o endereçamento baseado em nome, em que os links têm o formato
dbs/MyDatabaseId/colls/MyCollectionId/docs/MyDocumentId, em vez de SelfLinks (_self), que têm o formatodbs/<database_rid>/colls/<collection_rid>/docs/<document_rid>para evitar a recuperação de ResourceIds de todos os recursos usados para construir o link. Além disso, à medida que esses recursos são recriados (possivelmente com o mesmo nome), o cache deles pode não ser eficaz.Ajustar o tamanho da página para consultas/feeds de leitura para melhorar o desempenho
Ao executar uma leitura em massa de documentos usando a funcionalidade de feed de leitura (por exemplo, readDocuments) ou ao emitir uma consulta SQL, os resultados serão retornados de forma segmentada se o conjunto de resultados for muito grande. Por padrão, os resultados são retornados em partes de 100 itens ou 1 MB, o que for atingido primeiro.
Para reduzir o número de trocas de informações pela rede necessárias para recuperar todos os resultados aplicáveis, você pode aumentar o tamanho da página usando o cabeçalho de solicitação x-ms-max-item-count para até 1000. Nos casos em que você precisa exibir apenas alguns resultados, por exemplo, se a interface do usuário ou a API do aplicativo retornar apenas 10 resultados por vez, você também poderá diminuir o tamanho da página para 10 para reduzir a taxa de transferência consumida para leituras e consultas.
Você também pode definir o tamanho da página usando o método setMaxItemCount.
Usar o Agendador Apropriado (Evitar roubo de threads Netty de E/S Eventloop)
O SDK Java Assíncrono do Azure Cosmos DB v2 usa netty para E/S não bloqueante. O SDK usa um número fixo de threads de eventloop netty de E/S (como muitos núcleos de CPU que seu computador possui) para executar operações de E/S. O Observável retornado pela API emite o resultado em um dos threads do Netty compartilhados no loop de eventos de E/S. Portanto, é importante não bloquear os threads de netty eventloop de E/S compartilhados. Executar uma operação de bloqueio ou trabalho intensivo de CPU na thread do Netty no loop de eventos de E/S pode causar deadlock ou reduzir significativamente a taxa de transferência do SDK.
Por exemplo, o código a seguir executa um trabalho intensivo de CPU no thread de E/S do loop de eventos do Netty:
SDK Java Async V2 (Maven com.microsoft.azure::azure-cosmosdb)
Observable<ResourceResponse<Document>> createDocObs = asyncDocumentClient.createDocument( collectionLink, document, null, true); createDocObs.subscribe( resourceResponse -> { //this is executed on eventloop IO netty thread. //the eventloop thread is shared and is meant to return back quickly. // // DON'T do this on eventloop IO netty thread. veryCpuIntensiveWork(); });Após o resultado ser recebido, se você quiser realizar um trabalho intensivo de CPU no resultado, evite fazê-lo na thread de E/S do loop de eventos IO do Netty. Em vez disso, você pode fornecer seu próprio scheduler para criar sua própria thread para realizar suas tarefas.
SDK do Java Assíncrono V2 (Maven com.microsoft.azure::azure-cosmosdb)
import rx.schedulers; Observable<ResourceResponse<Document>> createDocObs = asyncDocumentClient.createDocument( collectionLink, document, null, true); createDocObs.subscribeOn(Schedulers.computation()) subscribe( resourceResponse -> { // this is executed on threads provided by Scheduler.computation() // Schedulers.computation() should be used only when: // 1. The work is cpu intensive // 2. You are not doing blocking IO, thread sleep, etc. in this thread against other resources. veryCpuIntensiveWork(); });Com base no tipo de seu trabalho, você deve usar o agendador RxJava existente apropriado para seu trabalho. Leia aqui
Schedulers.Para obter mais informações, examine a página do GitHub para o SDK Java Assíncrono do Azure Cosmos DB v2.
Desabilitar o log da Netty
O log da Biblioteca Netty é verborrágico e precisa ser desativado (suprimir o log na configuração pode não ser suficiente) para evitar custos adicionais de CPU. Se você não estiver no modo de depuração, desabilite o registro em log do netty completamente. Portanto, se você estiver usando log4j para remover os custos adicionais de CPU incorridos pela
org.apache.log4j.Category.callAppenders()netty, adicione a seguinte linha à sua base de código:org.apache.log4j.Logger.getLogger("io.netty").setLevel(org.apache.log4j.Level.OFF);Limite de recursos de arquivos abertos do SO
Alguns sistemas Linux (como Red Hat) têm um limite superior no número de arquivos abertos e, portanto no número total de conexões. Execute o seguinte para exibir os limites atuais:
ulimit -aO número máximo de arquivos abertos (nofile) precisa ser suficientemente grande para acomodar o tamanho do pool de conexões configurado e outros arquivos abertos pelo sistema operacional. Isso pode ser modificado para permitir um maior tamanho de pool de conexão.
Abra o arquivo limits.conf:
vim /etc/security/limits.confAdicione/modifique as linhas a seguir:
* - nofile 100000
Política de indexação
Excluir caminhos não utilizados da indexação para ter gravações mais rápidas
A política de indexação do Azure Cosmos DB permite que você especifique quais caminhos de documentos devem ser incluídos ou excluídos da indexação usando os caminhos de indexação (setIncludedPaths e setExcludedPaths). O uso dos caminhos de indexação pode oferecer um melhor desempenho de gravação e menor armazenamento de índices para os cenários nos quais os padrões da consulta são conhecidos com antecedência, pois os custos da indexação estão correlacionados diretamente com o número de caminhos exclusivos indexados. Por exemplo, o código a seguir mostra como excluir uma seção inteira dos documentos (também conhecida como subárvore) da indexação usando o curinga "*".
SDK do Java Assíncrono V2 (Maven com.microsoft.azure::azure-cosmosdb)
Index numberIndex = Index.Range(DataType.Number); numberIndex.set("precision", -1); indexes.add(numberIndex); includedPath.setIndexes(indexes); includedPaths.add(includedPath); indexingPolicy.setIncludedPaths(includedPaths); collectionDefinition.setIndexingPolicy(indexingPolicy);Para obter mais informações, consulte Políticas de indexação do Azure Cosmos DB.
Rendimento
Medir e ajustar para o uso mais baixo de unidades/segundo da solicitação
O Azure Cosmos DB oferece um conjunto avançado de operações do banco de dados, incluindo consultas relacionais e hierárquicas com UDFs, procedimentos armazenados e gatilhos – todos operando nos documentos em uma coleção de banco de dados. O custo associado a cada uma dessas operações varia com base na CPU, E/S e memória necessárias para concluir a operação. Em vez de pensar em e gerenciar recursos de hardware, você pode pensar em uma RU (unidade de solicitação) como uma medida única para os recursos necessários para realizar várias operações de bancos de dados e atender a uma solicitação do aplicativo.
A taxa de transferência é provisionada com base no número de unidades de solicitação definidas para cada contêiner. O consumo da unidade de solicitação é avaliado em termos de taxa por segundo. Os aplicativos que excedem a taxa das unidades de solicitação provisionada para seu contêiner serão limitados até que a taxa fique abaixo do nível reservado para o contêiner. Caso o aplicativo exija um nível mais alto de taxa de transferência, é possível aumentar a taxa de transferência provisionando unidades de solicitação adicionais.
A complexidade de uma consulta afeta a quantidade de unidades de solicitação consumida para uma operação. O número de predicados, natureza dos predicados, número de UDFs e tamanho do conjunto de dados de origem influenciam o custo das operações de consulta.
Para medir a sobrecarga de qualquer operação (criar, atualizar ou excluir), examine o cabeçalho x-ms-request-charge para medir o número de unidades de solicitação consumidas por essas operações. Você também pode examinar a propriedade RequestCharge equivalente em ResourceResponse<T> ou FeedResponse<T>.
SDK do Java Assíncrono V2 (Maven com.microsoft.azure::azure-cosmosdb)
ResourceResponse<Document> response = asyncClient.createDocument(collectionLink, documentDefinition, null, false).toBlocking.single(); response.getRequestCharge();A carga de solicitação retornada nesse cabeçalho é uma fração de sua taxa de transferência provisionada. Por exemplo, se você tiver 2.000 RU/s provisionados e se a consulta anterior retornar 1.000 documentos de 1 KB, o custo da operação será 1000. Assim, em um segundo, o servidor mantém apenas duas dessas solicitações antes de limitar as solicitações subsequentes. Para saber mais, consulte Unidades de solicitação e a calculadora das unidades de solicitação.
Lidar com uma limitação da taxa/taxa de solicitação muito grande
Quando um cliente tentar exceder a taxa de transferência reservada para uma conta, não haverá nenhuma degradação de desempenho no servidor e nenhum uso da capacidade da taxa além do nível reservado. O servidor encerrará antecipadamente a solicitação com RequestRateTooLarge (código de status HTTP 429) e retornará o cabeçalho x-ms-retry-after-ms indicando a quantidade de tempo, em milissegundos, que o usuário deve aguardar antes de tentar novamente a solicitação.
HTTP Status 429, Status Line: RequestRateTooLarge x-ms-retry-after-ms :100Os SDKs irão capturar implicitamente essa resposta, respeitarão o cabeçalho server-specified retry-after e repetirão a solicitação. A menos que sua conta esteja sendo acessada simultaneamente por vários clientes, a próxima tentativa será bem-sucedida.
Se você tiver mais de um cliente operando cumulativamente consistentemente acima da taxa de solicitação, a contagem de repetição padrão atualmente definida como 9 internamente pelo cliente pode não ser suficiente; nesse caso, o cliente lança um DocumentClientException com o código de status 429 para o aplicativo. A contagem de repetição padrão pode ser alterada usando setRetryOptions na instância connectionPolicy. Por padrão, o DocumentClientException com o código de status 429 é retornado após um tempo de espera cumulativo de 30 segundos se a solicitação continuar operando acima da taxa de solicitação. Isso ocorre mesmo quando a contagem de repetição atual é menor que a contagem de repetição máxima, seja o padrão 9 seja um valor definido pelo usuário.
Embora o comportamento de repetição automática ajude a melhorar a resiliência e a utilidade da maioria dos aplicativos, ela pode entrar em conflito ao fazer comparações de desempenho, especialmente ao medir a latência. A latência medida pelo cliente terá um pico se o experimento atingir o limite de capacidade do servidor e levar o SDK do cliente a repetir silenciosamente. Para evitar picos de latência durante os testes de desempenho, meça o custo retornado por cada operação e verifique se as solicitações estão operando abaixo da taxa de solicitação reservada. Para saber mais, consulte Unidades de solicitação.
Design de documentos menores para uma maior taxa de transferência
O custo da solicitação (o custo de processamento da solicitação) de uma determinada operação está correlacionado diretamente com o tamanho do documento. As operações em documentos grandes custam mais que as operações de documentos pequenos.
Próximas etapas
Para saber mais sobre como projetar seu aplicativo para escala e alto desempenho, consulte Particionamento e escala no Azure Cosmos DB.