Como posso evitar a proliferação de objetos de conexão RabbitMQ obsoletos/falsos no plug-in de gerenciamento sem atualizar o servidor?

Como posso evitar a proliferação de objetos de conexão RabbitMQ obsoletos/falsos no plug-in de gerenciamento sem atualizar o servidor?

Contexto:

Usamos um cluster RabbitMQ 2.8.4 HA para mensagens em um datacenter de tamanho médio (centenas a milhares de servidores). As funções de mensagens são essenciais para nosso aplicativo.

Usamos a API do cliente C para operações AMQP/RabbitMQ e a API HTTP para o plug-in de gerenciamento RabbitMQ para monitorar periodicamente o status da fila e enviar alertas com base no tamanho/taxa de transferência/etc.

As únicas portas/conexões permitidas de clientes para os servidores de mensagens estão nas portas AMQP e em HTTP para a API de gerenciamento.

No futuro próximo, a administração decidiu que o tempo de inatividade do cluster de mensagens (que se traduz em tempo de inatividade para determinadas partes solicitantes do aplicativo) é inaceitável. Dentro de alguns meses isso será possível, mas até lá as preocupações de vendas não nos permitirão manter o sistema de mensagens. É uma droga, mas nós (o pessoal de infraestrutura/devops) não conseguimos fazer essas ligações.

Problema:

Durante algum tempo, fomos vitimados pelo problema discutido emesta pergunta SO. Após uma tempestade de conexões ou um longo período durante o qual novos clientes se conectam e usam o sistema AMQP com muita frequência, a API de gerenciamento RabbitMQ mostra centenas de milhares de conexões listadas como "em execução" que não existem mais. netstat, lsofe outros diagnósticos comprovam que os soquetes correspondentes a essas conexões não estão abertos nos clientes; a API de gerenciamento simplesmente não consegue remover as entradas por algum motivo. rabbitmqctl list_connectionsàs vezes mostra que algumas das conexões inexistentes ainda estão abertas, mas sempre mostra muito menos do que a API de gerenciamento, e sua detecção de "desatualização" parece melhor que a da API e, eventualmente, elimina as conexões falsas de sua listagem.

Quando tentamos excluir uma dessas conexões "falsas" por meio da interface da web, a página não responde ao pressionar "excluir" e a conexão permanece na listagem. Quando tentamos excluí-lo enviando um DELETE na API JSON, obtemos um erro de servidor 500 indicando que a conexão não é válida, portanto não pode ser excluída (exatamente como descrito na pergunta SO vinculada acima).

Após uma longa acumulação desses objetos de conexão inexistentes, três coisas ruins acontecem, sem nenhuma ordem específica:

  • O servidor RabbitMQ tem picos massivos de memória (que surgem do nada; eles não correspondem ao aumento lento da conexão na API de gerenciamento, embora seu consumo de memória cresça lentamente com o tempo). Isso geralmente leva a um travamento.
  • A API de gerenciamento para de responder às solicitações (expira o tempo limite nos clientes da API).
  • O próprio servidor RabbitMQ começa a recusar esporadicamente conexões de clientes AMQP que não estão fazendo nada com HTTP/API de gerenciamento.

Nos casos em que esse problema começa a interromper nosso aplicativo, temos que fazer uma de duas coisas: * Reiniciar todo o cluster de mensagens, o que é ruim porque causa tempo de inatividade momentâneo e ruim porque as mensagens podem ser descartadas durante esse processo. * Reinicie e limpe o banco de dados da API de gerenciamento, o que é ruim porque não podemos usar a API de gerenciamento, e pior porque muitas vezes quebra a API de gerenciamento de tal forma que ela não será iniciada corretamente novamente até reiniciarmos todo o cluster como em a primeira bala.

A maioria das pessoas que sofrem de problemas semelhantes os resolvem atualizando para o RabbitMQ 3.*. Não temos tempo, permissão ou autorização de tempo de inatividade para tal projeto. Mesmo diante de interrupções periódicas de vários minutos quando reiniciamos o cluster devido a esse problema, não fomos autorizados a atualizar. É uma restrição puramente política, mas uma triste realidade.

Pergunta:

Considerando que não poderemos atualizar o RabbitMQ em um futuro próximo e que precisamos continuar usando a API de gerenciamento, como podemos resolver o problema de conexões obsoletas e persistentes que causam falhas no cluster de mensagens?

Temos a capacidade de desenvolver código de cliente novo/diferente e executar trabalhos nos próprios servidores de mensagens, mas não temos a capacidade de usar rabbitmqctllocalmente ou via sshem qualquer uma das máquinas clientes.

O que tentamos:

  • Tentamos trocar as bibliotecas de cliente AMQP na esperança de que um cliente melhor se limpasse e não deixasse conexões obsoletas, sem sucesso. O problema persiste.
  • Tentamos brincar com as configurações tcp_keepalivee exit_on_closeTCP nos próprios servidores RabbitMQ. Nenhuma combinação desses valores resolve o problema.
  • Criamos um script que itera sobre todas as conexões retornadas da lista de conexões da API JSON e envia um DELETE para cada uma que está aberta há mais tempo do que precisaria se estivesse sendo usada. Todas essas solicitações são atendidas com 500 erros de servidor, conforme descrito na pergunta SO vinculada acima.

Responder1

Você continua reiniciando tudo periodicamente.

A outra opção é fazer backport da correção 3.x para sua versão atual, mas se você não tiver permissão para atualizar, provavelmente também não terá permissão para fazer isso. E quase certamente será muito mais trabalhoso do que atualizar, especialmente se o código RabbitMQ tiver sido significativamente refatorado.

Até que você possa mudar opolíticada situação, essas são suas opções.

informação relacionada