Engenharia

Práticas recomendadas de sniffing do Elasticsearch: o que, quando, por que, como

O Elasticsearch melhora as experiências de busca para diversas ferramentas e aplicações usadas atualmente, desde dashboards de analítica operacional até mapas que mostram os restaurantes mais próximos com áreas externas para que você possa se sentar ao ar livre. E em todas essas implementações, a conexão entre a aplicação e o cluster é feita por meio de um cliente do Elasticsearch.

Otimizar a conexão entre o cliente e o cluster do Elasticsearch é extremamente importante para a experiência do usuário final. A configuração típica de um cliente do Elasticsearch é o URL do nó ao qual você deve se conectar. Mas há muito mais que você pode fazer, e uma forma de otimizar essa conexão é por meio do sniffing.

Veja como o sniffing funciona, quando você deve usá-lo e como saber quando evitá-lo.

O que é o sniffing?

O Elasticsearch é um sistema distribuído, o que significa que seus índices residem em vários nós conectados entre si, formando um cluster. Uma das principais vantagens de ser um sistema distribuído — além da tolerância a falhas — é que os dados são fragmentados em vários nós, permitindo que as buscas sejam executadas muito mais rapidamente do que as executadas em um único nó bem grande.

Uma configuração de cliente típica é um único URL que aponta para um nó do cluster do Elasticsearch. Embora essa seja a configuração mais simples, a principal desvantagem dela é que todas as solicitações feitas serão enviadas para esse nó de coordenação específico. Como isso coloca um único nó sob estresse, o desempenho geral pode ser afetado.

Uma solução é passar uma lista estática de nós ao cliente, para que suas solicitações sejam distribuídas igualmente entre os nós.

Ou você pode habilitar um recurso chamado sniffing.

Com uma lista estática de nós, não há garantia de que os nós estarão sempre ativos e em funcionamento. Por exemplo, o que acontece se você desativa um nó para atualização ou adiciona novos nós?

Se você habilitar o sniffing, o cliente começará a chamar o endpoint _nodes/_all/http, e a resposta será uma lista de todos os nós presentes no cluster, junto com seus endereços IP. Em seguida, o cliente atualizará seu pool de conexões para usar todos os novos nós e manterá o estado do cluster sincronizado com o pool de conexões do cliente. Observe que, mesmo que os clientes baixem a lista completa de nós, os nós que forem somente master não serão usados para chamadas de API genéricas.

O sniffing resolve esse problema de descoberta. Então, por que ele não é habilitado por padrão? Essa é uma excelente pergunta!

Quando usar o sniffing?

O sniffing pode ser uma faca de dois gumes. Se você tentar chamar o endpoint _nodes/_all/http, verá uma lista de nós e seus respectivos endpoints. Mas há algumas questões a serem consideradas:

  • O que acontecerá se o seu cluster do Elasticsearch residir em sua própria rede?
  • E se o seu cluster do Elasticsearch ficar atrás de um balanceador de carga?

A resposta curta para ambas: você obterá endereços IP completamente inúteis porque está em uma rede diferente.

Você pode tentar isso por conta própria com o Docker. Crie uma instância do Elasticsearch (uma é o suficiente) e chame _nodes/_all/http da sua máquina local. Você verá que o endereço IP do seu nó não será o mesmo endereço IP que você acabou de usar.

Use-o com o seguinte comando para inicializar uma instância do Elasticsearch:

docker run \ 
-p 9200:9200 \
-e "discovery.type=single-node" \
docker.elastic.co/elasticsearch/elasticsearch:7.8.0

Agora você pode ler o IP do nó com o comando a seguir. No snippet abaixo, estamos usando jq para facilitar a leitura da resposta:

curl -s localhost:9200/_nodes/_all/http | jq .nodes[].http.publish_address

Por fim, você pode copiar o endereço IP impresso no terminal e tentar enviar uma solicitação para ele:

curl {ip_address}:9200 | jq .

Como pode ver, você não obterá uma resposta bem-sucedida.

Isso significa que, se você habilitar o sniffing em um cliente enquanto o cluster estiver em outra rede, o cliente adicionará todos os novos nós ao seu pool de conexões. Isso ocorre porque ele não tem como entender que esses endereços IP estão errados, e todas as consultas em um desses nós falharão.

Como o nó inicial com o endereço IP correto não está mais presente no estado do cluster, ele será descartado, e você receberá um erro “no living connections” (sem conexões ativas) muito rapidamente.

Mas podemos consertar isso.

Para resolver esse problema, você pode configurar o Elasticsearch para se vincular ao seu host, mas anunciar outro. A opção de configuração http.publish_host faz exatamente isso. Agora tente executar o comando do Docker acima com esta nova configuração:

docker run \ 
-p 9200:9200 \
-e "discovery.type=single-node" \
-e "http.publish_host=localhost" \
docker.elastic.co/elasticsearch/elasticsearch:7.8.0

Agora, se você executar o seguinte comando novamente:

curl -s localhost:9200/_nodes/_all/http | jq .nodes[].http.publish_address

No terminal você verá:

"localhost/{ip_address}:9200"

Se você configurar o host de publicação, os clientes oficiais (da versão 7 e superiores) serão inteligentes o suficiente para usar o endereço do host em vez do IP.

A principal conclusão disso é que você deve conhecer sua infraestrutura antes de habilitar o sniffing. Existem muitas soluções para esse problema de endereço IP e não existe uma solução mágica, porque tudo depende da configuração do seu sistema.

A configuração típica de desenvolvimento é ter o cluster do Elasticsearch na mesma rede que seu cliente, mas isso não pode ser replicado no mundo real, pois causaria problemas de segurança — e sua infraestrutura provavelmente seria mais complexa. Você poderia configurar o balanceador de carga para lidar com esses endereços IP. Ou, como a Elastic faz no Elastic Cloud, pode deixar o proxy lidar com os nós com falha para que o cliente sempre envie as consultas ao proxy, que então as enviará ao nó apropriado.

Quando não usar o sniffing?

Existem muitas situações em que o sniffing pode causar alguns problemas, como as seguintes:

  • O usuário do Elasticsearch com o qual seu cliente está se autenticando não tem as permissões corretas (função monitoring_user) para acessar a API de nós.
  • Você está trabalhando com provedores de serviços em nuvem.

Normalmente, os provedores de serviços em nuvem escondem o Elasticsearch atrás de um proxy, o que tornaria a operação de sniffing inútil, já que os endereços e nomes de host retornados podem não ter significado na sua rede. Normalmente, esses provedores lidam com a complexidade do sniffing e do pooling para você, portanto, você não precisa habilitá-los.

Se você estiver usando o Elastic Cloud, os clientes oficiais causarão um curto-circuito na maioria das operações internamente, como a manipulação do pool de conexões, para evitar gastar tempo em operações que já foram realizadas.

Outros problemas, como vimos antes, podem ocorrer ao trabalhar com o Docker ou o Kubernetes. A menos que você configure a opção de host de publicação, o resultado do sniffing será inutilizável.

Como um princípio básico: Se o Elasticsearch residir em uma rede diferente da do seu cliente — ou se houver um balanceador de carga —, o sniffing deverá ser desabilitado, a menos que haja alguma configuração na infraestrutura que lhe permita usá-lo com precisão.

Como usar o sniffing?

Os clientes oferecem várias estratégias de sniffing. Vamos analisá-las:

Sniffing na inicialização

Como o nome sugere, quando você habilitar essa opção, o cliente tentará executar uma solicitação de sniff uma vez apenas, durante a inicialização do cliente ou no primeiro uso.

Sniffing na falha de conexão

Se você habilitar essa opção, o cliente tentará executar uma solicitação de sniff toda vez que um nó estiver com problema, ou seja, uma conexão interrompida ou um nó morto.

Intervalo de sniff

Além do sniffing na inicialização e do sniffing em falhas, fazer o sniffing periodicamente pode beneficiar cenários em que os clusters costumam ser redimensionados horizontalmente durante horários de pico. Uma aplicação pode ter uma visão íntegra de um subconjunto dos nós. Mas sem fazer um sniffing periodicamente, ela nunca encontrará os nós que foram adicionados como parte do redimensionamento horizontal.

Configurações customizadas

Em alguns casos, você pode querer ter um controle mais refinado sobre o procedimento de sniffing. Os clientes são flexíveis o suficiente para permitir que você configure um endpoint de sniffing customizado, ou você pode substituir totalmente a lógica de sniffing e fornecer uma de sua preferência.

Conclusões

Ao habilitar o sniffing, você tornará sua aplicação mais resiliente e capaz de se adaptar às mudanças. Antes de fazer isso, você deve conhecer sua infraestrutura para decidir qual a melhor solução a adotar. A melhor solução pode até ser não adotar o sniffing.

Se quiser evitar pensar em sniffing e na configuração do pool de conexões e, em vez disso, usar uma string de conexão simples, experimente o Elastic Cloud com uma avaliação gratuita por 14 dias do nosso Elasticsearch Service.