Logo Passei Direto

Estudo sobre quedas do ElasticSearch

User badge image

Sent by Paul Snow in

This is a file preview. Join to view the original file.

Estudo sobre quedas do ElasticSearch
[SITE-1468] Descobrir o motivo do ElasticSearch estar caindo
Introdução
O ElasticSearch do ambiente de produção (site) estava apresentando muito instablidade, travando várias vezes ao dia por motivo desconhecido. Esse problema existia há meses, ficando mais frequente recentemente. Quando ocorre o problema, o servidor continua respondendo, porém nenhuma query funciona mais (retornam um código de erro). Em alguns casos extremos, o servidor para de responder.
Investigação
Comecei a investigação estudando mais a fundo o funcionamento do ElasticSearch.
Encontrei alguns artigos bons que discutem como otimizar / escalar o ES:
http://gibrown.wordpress.com/2014/01/09/scaling-elasticsearch-part-1-overview/
http://gibrown.wordpress.com/2014/02/06/scaling-elasticsearch-part-2-indexing/
e
http://blog.trifork.com/2013/09/26/maximum-shard-size-in-elasticsearch/
http://blog.trifork.com/2013/11/05/maximum-shard-size-in-elasticsearch-revisited/
http://blog.trifork.com/2014/01/07/elasticsearch-how-many-shards/
Sobre algumas configurações básicas:
http://asquera.de/opensource/2012/11/25/elasticsearch-pre-flight-checklist/
http://stackoverflow.com/questions/18132719/how-to-change-elasticsearch-max-size/
Em seguida, peguei os logs de produção e ativei o “Slowlog” (feature do ES que permite logar queries demoradas) com o Beildeck.
- Vários erros no log ocorreram por conta de caracteres inválidos (user input) em algumas buscas
- A maioria dos erros eram exceções que indicavam que o request foi abortado por conta do limite de threads. O ElasticSearch possui threadpools para realizar as buscas. Quando o pool fica cheio, ele adiciona as threads em uma fila. Quando chega no limite dessa fila, os novos requests são simplesmente abortados.
- A maioria das queries que apareceram no Slowlog ocorreram em horários próximos aos momentos em que o ES travou. Começam a aparecer cerca de 1 hora antes e vão aumentando até o momento em que tudo para.
Por fim, tentei reproduzir o problema, primeiro em dev e depois em produção mesmo. A estratégia foi usar o JMeter para fazer muitos requests simultâneos ao ES.
Nos dois ambientes o comportamento foi semelhante. Após atingir determinado número de requests por segundo, o ES passa a retornar status code 503 (serviço indisponível), devido ao limite do número de threads na fila.
Isso é semelhante ao erro que estava derrubando o ES em produção. A diferença é que nessa simulação de testes, após cessarem os requests, o ES volta a funcionar normalmente. Quando o erro acontece em produção, o ES não volta a funcionar sozinho (é preciso reiniciar o serviço).
Não consegui reproduzir o cenário real do erro.
Resultados
a) O problema de queda foi aparentemente resolvido alocando mais memória para o processo do ES, através da variável de ambiente ES_HEAP_SIZE. Antes estava sendo alocado apenas 1.75GB, agora está com 6.0GB. A recomendação é deixar 50% da memória da máquina para o ES. Essa solução é imediatista, provavelmente com crescimento dos índices e aumento da demanda o erro voltará a se manifestar.
b) Para escalar, é preciso montar um cluster. Parece ser simples de configurar o cluster, mas devemos fazer testes antes de precisar de fato. Testes constantes de configuração (dos nós e dos índices) são importantes para aprender a otimizar o cluster também.
c) Ainda assim, não consegui reproduzir o problema como ele ocorria em produção (parar de responder e só voltar ao reiniciar o serviço). Pode ser algum bug do próprio ES ativado por alguma query que fazemos. Ou pode ser qualquer outra coisa...
d) O desempenho do nosso ES está muito ruim. Para uma query testada no índice de arquivos, o ES não passou de 70 responses/s e rapidamente cada request chegou a demorar mais de 1s. É preciso fazer mais testes de carga com outras queries. O problema pode ser de configuração ou pode ser que nossas queries sejam complexas demais. É preciso investigar.
e) Analisando os logs, identifiquei um bug. Em muitos casos passamos caracteres inválidos (que os usuários digitam) para as queries o que gera um ParseError e a busca do usuário retorna erro.
f) Os logs do ES são muito úteis. O log padrão mostra os erros que acontecem. Com isso podemos verificar as queries bugadas. É também um ponto de partida para tentar descobrir o que aconteceu quando o servidor trava. O “Slowlog” loga as queries (de indexação e de busca) mais lentas, de forma que podemos verificar os pontos que precisam ser mais otimizados.
g) Artigo que encontrei e pode ser útil, relacionado à fila de threads, porém não testei:
http://jontai.me/blog/2013/06/esrejectedexecutionexception-rejected-execution-of-messagechannelhandler-requesthandler/
12/05/2014