Como solucionar problemas de exceção do interruptor no Amazon OpenSearch Service?

Data da última atualização: 01/09/2021

Estou tentando enviar dados para meu cluster do Amazon OpenSearch Service (sucessor do Amazon Elasticsearch Service). No entanto, recebo um erro de exceção de disjuntor que afirma que meus dados são muito grandes. Por que isso está acontecendo e como resolvo isso?

Breve descrição

Quando uma solicitação chega aos nós do OpenSearch Service, os disjuntores estimam a quantidade de memória necessária para carregar os dados necessários. Em seguida, o OpenSearch Service compara o tamanho estimado ao limite de tamanho de heap configurado. Se o tamanho estimado dos dados for maior que o tamanho de heap disponível, a consulta será encerrada. Como resultado, é lançado um CircuitBreakerException para evitar a sobrecarga do nó.

O OpenSearch Service usa estes disjuntores para evitar exceções JVM OutofMemoryError:

  • Solicitação
  • Dados de campo
  • Solicitações dinâmicas
  • Contabilidade
  • Pai

Observação: é importante saber qual desses cinco disjuntores disparou a exceção, porque cada disjuntor tem suas próprias necessidades de ajuste. Para obter mais informações sobre os tipos de disjuntores, consulte Configurações do disjuntor no site do Elasticsearch.

Para obter o uso atual da memória por nó e por disjuntor, use o seguinte comando:

GET _nodes/stats/breaker

Além disso, observe que os disjuntores são apenas um mecanismo com base no melhor esforço. Embora os disjuntores forneçam alguma resiliência contra a sobrecarga de um nó, ainda é possível acabar recebendo um OutOfMemoryError. Os disjuntores só podem monitorar a memória se ela estiver explicitamente reservada. Portanto, nem sempre é possível estimar o uso exato da memória antecipadamente. Por exemplo, se você tiver uma pequena quantidade de heap de memória, a sobrecarga relativa da memória não monitorada será maior. Para obter mais informações sobre disjuntores e resiliência de nó, consulte Aprimorar a resiliência de nó com o disjuntor de memória real no site do Elasticsearch.

Para evitar sobrecarregar os nós de dados, siga as dicas fornecidas na seção Solucionar problemas de alta pressão de memória da JVM.

Resolução

Exceção de disjuntor

Se você estiver usando o Elasticsearch versão 7.x ou posterior com 16 GB de heap, receberá o seguinte erro quando o limite do disjuntor for atingido:

"error": {
        "root_cause": [
            {
                "type": "circuit_breaking_exception",
                "reason": "[parent] Data too large, data for [<http_request>] would be [16355096754/15.2gb], which is larger than the limit of [16213167308/15gb], real usage: [15283269136/14.2gb], new bytes reserved: [1071827618/1022.1mb]",
               }
      ]
}

Esse exemplo de saída indica que os dados a serem processados são muito grandes para o disjuntor pai manipular. O disjuntor pai (um tipo de disjuntor) é responsável pelo uso geral de memória do cluster. Quando ocorre uma exceção de disjuntor pai, a memória total usada em todos os disjuntores excedeu o limite definido. Um disjuntor pai lança uma exceção quando o cluster excede 95% de 16 GB, ou seja, 15,2 GB de heap.

Você pode verificar essa lógica calculando a diferença entre o uso de memória e o limite definido para o disjuntor. Use os valores do nosso exemplo de saída e subtraia “real usage: [15283269136/14.2gb]” de “limit of [16213167308/15gb]”. Esse cálculo mostra que essa solicitação precisa de cerca de 1,02 GB de memória reservada de novos bytes para processar a solicitação corretamente. No entanto, neste exemplo, o cluster tinha menos de 0,8 GB de heap de memória livre disponível quando a solicitação de dados chegou. Como resultado, o disjuntor dispara.

A mensagem de exceção do disjuntor pode ser interpretada assim:

  • data for [ ] (dados para): o cliente envia solicitações HTTP a um nó no cluster. O OpenSearch Service processa a solicitação localmente ou a transmite para outro nó para processamento adicional.
  • would be [#] (seria [n.º]): como fica o tamanho do heap quando a solicitação é processada.
  • limit of [#] (limite de [n.º]): limite do disjuntor atual.
  • real usage (uso real): uso real do heap da JVM.
  • new bytes reserved (novos bytes reservados): memória real necessária para processar a solicitação.

Pressão de memória da JVM

Uma exceção de quebra de circuito geralmente é causada pela alta pressão da memória da JVM. A pressão da memória da JVM refere-se à porcentagem de heap Java usada para todos os nós de dados no cluster. Verifique a métrica JVMMemoryPressure no Amazon CloudWatch para determinar o uso atual.

Observação: o tamanho do heap da JVM de um nó de dados é definido como metade do tamanho da memória física (RAM), até 32 GB. Por exemplo, se a memória física (RAM) for 128 GB por nó, o tamanho da pilha ainda será de 32 GB (o tamanho máximo do heap). Caso contrário, o tamanho da pilha é calculado como metade do tamanho da memória física.

A alta pressão da memória JVM pode ser causada pelo seguinte:

  • Aumento no número de solicitações para o cluster. Verifique as métricas IndexRate e SearchRate no Amazon CloudWatch para determinar sua carga atual.
  • Agregação, curingas e uso de amplos intervalos de tempo em suas consultas.
  • Alocação de fragmentos desbalanceada entre nós ou muitos fragmentos em um cluster.
  • Explosões de mapeamento de índice.
  • Usar a estrutura de dados fielddata para consultar dados. O fielddata pode consumir uma grande quantidade de espaço de heap e permanecer no heap durante toda a vida útil de um segmento. Como resultado, a pressão da memória da JVM permanece alta no cluster quando o fielddata é usado. Para obter mais informações, consulte Fielddata no site do Elasticsearch.

Solução de problemas de alta pressão da memória da JVM

Para resolver a alta pressão da memória da JVM, tente as seguintes dicas:

  • Reduza o tráfego de entrada para o cluster, especialmente se você tiver um workload pesado.
  • Analise a possibilidade de escalar o cluster para obter mais memória da JVM para dar suporte ao seu workload.
  • Se a escalabilidade do cluster não for possível, tente reduzir o número de fragmentos excluindo índices antigos ou não usados. Como os metadados do fragmento são armazenados na memória, reduzir o número de fragmentos poderá reduzir o uso geral da memória.
  • Habilite logs lentos para identificar solicitações com defeito.
    Observação: antes de ativar as alterações de configuração, verifique se a pressão da memória da JVM está abaixo de 85%. Dessa forma, é possível evitar sobrecarga adicional dos recursos existentes.
  • Otimize as solicitações de pesquisa e indexação e escolha o número correto de fragmentos. Para obter mais informações sobre indexação e contagem de fragmentos, consulte Conceitos básicos sobre o Amazon OpenSearch Service: de quantos fragmentos eu preciso?
  • Desabilite e evite usar o fielddata. Por padrão, o fielddata é definido como “false” em um campo de texto, a menos que seja explicitamente definido como de outra forma nos mapeamentos de índice.
  • Altere o tipo de mapeamento de índice para uma palavra-chave usando a API reindex ou crie ou atualize a API de modelo de índice. É possível usar o tipo de palavra-chave como alternativa para realizar agregações e classificação em campos de texto.
  • Evite agregar em campos de texto para evitar aumentos nos dados de campo. Quando você usa mais dados de campo, mais espaço de heap é consumido. Use a operação da API cluster stats para verificar seus dados de campo.
  • Limpe o cache de fielddata com a seguinte chamada de API:
POST /index_name/_cache/clear?fielddata=true (index-level cache)
POST */_cache/clear?fielddata=true (cluster-level cache)

Aviso: se você limpar o cache de fielddata, as consultas em andamento poderão ser interrompidas.

Para obter mais informações, consulte Como solucionar problemas de alta demanda de memória da JVM em meu cluster do Amazon OpenSearch Service?