Compartilhar via


Dicas de desempenho para o SDK de Sincronização do Java do Azure Cosmos DB v2

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.

Essas dicas de desempenho são apenas para o Azure Cosmos DB Sync Java SDK v2. Exiba o repositório Maven para obter mais informações.

Importante

Em 29 de fevereiro de 2024, o SDK do Java de Sincronização 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 diminuir a escala é tão fácil quanto fazer uma única chamada de API. Para saber mais, veja como provisionar a taxa de transferência do contêiner ou como provisionar a taxa de transferência do banco de dados. 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 do Java de Sincronização 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

  1. Modo de conexão: usar DirectHttps

    Como um cliente se conecta ao Azure Cosmos DB tem implicações importantes no desempenho, especialmente em termos de latência observada no lado do cliente. Há uma configuração de chave disponível para configurar o ConnectionPolicy do cliente – o ConnectionMode. Os dois ConnectionModes disponíveis são:

    1. Gateway (padrão)

    2. DirectHttps

      O modo de gateway tem suporte em todas as plataformas do SDK e é o padrão configurado. Se o aplicativo for executado em uma rede corporativa com restrições estritas de firewall, o 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 Cosmos DB. Por isso, o modo DirectHttps oferece melhor desempenho devido a menos saltos de rede.

      O SDK do Java de Sincronização do Azure Cosmos DB v2 usa HTTPS como um protocolo de transporte. O HTTPS usa o TLS para autenticação inicial e criptografia de tráfego. Ao usar o SDK do Java de Sincronização do Azure Cosmos DB v2, somente a porta HTTPS 443 precisa estar aberta.

      O ConnectionMode é configurado durante a construção da instância do DocumentClient com o parâmetro ConnectionPolicy.

    Sincronizar o SDK do Java V2 (Maven com.microsoft.azure::azure-documentdb)

    public ConnectionPolicy getConnectionPolicy() {
      ConnectionPolicy policy = new ConnectionPolicy();
      policy.setConnectionMode(ConnectionMode.DirectHttps);
      policy.setMaxPoolSize(1000);
      return policy;
    }
    
    ConnectionPolicy connectionPolicy = new ConnectionPolicy();
    DocumentClient client = new DocumentClient(HOST, MASTER_KEY, connectionPolicy, null);
    

    O diagrama mostra a política de conexão do Azure Cosmos DB.

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

    O diagrama mostra solicitações e respostas em duas regiões, em que os computadores se conectam a uma conta do Azure Cosmos DB por meio de serviços de camada intermediária.

Uso do SDK

  1. Instalar o SDK mais recente

    Os SDKs do Azure Cosmos DB estão constantemente sendo aprimorados para fornecer o melhor desempenho. Para determinar as melhorias mais recentes do SDK, visite o SDK do Azure Cosmos DB.

  2. Usar um cliente do Azure Cosmos DB singleton para obter o tempo de vida do aplicativo

    Cada instância do DocumentClient é thread-safe e executa o gerenciamento eficiente de conexões e o cache de endereços ao operar no Modo Direto. Para permitir o gerenciamento eficiente de conexões e o melhor desempenho do DocumentClient, é recomendável usar uma única instância do DocumentClient por AppDomain durante o tempo de vida do aplicativo.

  3. Aumentar o MaxPoolSize por host ao usar o modo gateway

    As solicitações do Azure Cosmos DB são feitas por HTTPS/REST ao usar o modo gateway e são submetidas ao limite de conexão padrão por nome de host ou endereço IP. Talvez seja necessário definir o MaxPoolSize como um valor mais alto (200-1000) para que a biblioteca de clientes possa utilizar várias conexões simultâneas com o Azure Cosmos DB. No SDK do Java de Sincronização do Azure Cosmos DB v2, o valor padrão para ConnectionPolicy.getMaxPoolSize é 100. Use setMaxPoolSize para alterar o valor.

  4. Ajustando consultas paralelas para coleções particionadas

    O SDK do Java de Sincronização do Azure Cosmos DB versão 1.9.0 e superior 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.

    (a) Ajuste de setMaxDegreeOfParallelism: As consultas paralelas operam consultando várias partições simultaneamente. 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 têm a chance máxima de alcançar a consulta com maior desempenho, 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.

    (b) Ajustando setMaxBufferedItemCount: a consulta paralela foi projetada para pré-carregar os 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. Ao definir setMaxBufferedItemCount como o número esperado de resultados retornados (ou um número maior), isso 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.

  5. 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 ocorrer throttling, o aplicativo cliente deverá fazer o backoff pelo intervalo de nova tentativa especificado pelo servidor. Respeitar o backoff garante que você passe o mínimo de tempo aguardando entre tentativas. O suporte à política de repetição está incluído na versão 1.8.0 e superior do SDK java de sincronização do Azure Cosmos DB. Para obter mais informações, consulte getRetryAfterInMilliseconds.

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

  7. 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 formato dbs/<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 desses recursos pode não ajudar.

  8. 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 setPageSize.

Política de indexação

  1. 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 especificar quais caminhos de documento incluir ou excluir da indexação usando 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 (subárvore) dos documentos da indexação usando o curinga "*".

    Sincronizar o SDK do Java V2 (Maven com.microsoft.azure::azure-documentdb)

    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

  1. 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), inspecione o cabeçalho x-ms-request-charge (ou a propriedade RequestCharge equivalente em ResourceResponse<T> ou FeedResponse<T> para medir o número de unidades de solicitação consumidas por essas operações.

    Sincronizar o SDK do Java V2 (Maven com.microsoft.azure::azure-documentdb)

    ResourceResponse<Document> response = client.createDocument(collectionLink, documentDefinition, null, false);
    
    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 1KB-documents, o custo da operação será de 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.

  2. 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 :100
    

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

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