¿Cómo puedo evitar la proliferación de objetos de conexión RabbitMQ falsos o obsoletos en el complemento de administración sin actualizar el servidor?

¿Cómo puedo evitar la proliferación de objetos de conexión RabbitMQ falsos o obsoletos en el complemento de administración sin actualizar el servidor?

Contexto:

Usamos un clúster RabbitMQ 2.8.4 HA para mensajería en un centro de datos de tamaño mediano (cientos a miles de servidores). Las funciones de mensajería son fundamentales para nuestra aplicación.

Usamos la API del cliente C para operaciones AMQP/RabbitMQ y la API HTTP para el complemento de administración RabbitMQ para monitorear periódicamente el estado de la cola y enviar alertas según el tamaño/rendimiento/etc.

Los únicos puertos/conexiones permitidos desde los clientes a los servidores de mensajería están en los puertos AMQP y en HTTP para la API de administración.

En el futuro cercano, la administración ha decidido que el tiempo de inactividad del grupo de mensajería (lo que se traduce en tiempo de inactividad para ciertas partes solicitantes de la aplicación) es inaceptable. En unos meses será posible, pero hasta entonces las inquietudes comerciales no nos permitirán mantener el sistema de mensajería. Apesta, pero nosotros (la gente de infraestructura/devops) no podemos hacer esas llamadas.

Problema:

Durante algún tiempo hemos sido víctimas del problema discutido enesta pregunta SO. Después de una tormenta de conexiones, o de un largo período durante el cual nuevos clientes se conectan y utilizan el sistema AMQP con mucha frecuencia, la API de administración de RabbitMQ muestra cientos de miles de conexiones que enumera como "en ejecución" y que ya no existen. netstat, lsofy otros diagnósticos prueban que los sockets correspondientes a estas conexiones no están abiertos en los clientes; la API de administración simplemente no puede eliminar las entradas por algún motivo. rabbitmqctl list_connectionsa veces muestra que algunas de las conexiones inexistentes aún están abiertas, pero siempre muestra muchas menos que la API de administración, y su detección de "obsolescencia" parece mejor que la de la API y eventualmente elimina las conexiones falsas de su lista.

Cuando intentamos eliminar una de estas conexiones "falsas" a través de la interfaz de usuario web, la página no responde cuando presionamos "eliminar" y la conexión permanece en la lista. Cuando intentamos eliminarlo enviando un DELETE en la API JSON, obtenemos un error de servidor 500 que indica que la conexión no es válida, por lo que no se puede eliminar (exactamente como se describe en la pregunta SO vinculada anteriormente).

Después de una larga acumulación de estos objetos de conexión inexistentes, suceden tres cosas malas, sin ningún orden en particular:

  • El servidor RabbitMQ tiene picos de memoria masivos (que surgen de la nada; no se corresponden con la lentitud de la conexión en la API de administración, aunque su consumo de memoria crece lentamente con el tiempo). Esto a menudo conduce a un accidente.
  • La API de administración deja de responder a las solicitudes (se agota el tiempo de espera en los clientes de API).
  • El propio servidor RabbitMQ comienza a rechazar esporádicamente conexiones de clientes AMQP que no están haciendo nada con HTTP/la API de administración.

En los casos en que este problema comience a dañar nuestra aplicación, tenemos que hacer una de dos cosas: * Reiniciar todo el clúster de mensajería, lo cual es malo porque causa un tiempo de inactividad momentáneo y malo porque los mensajes se pueden descartar durante este proceso. * Reiniciar y purgar la base de datos de la API de administración, lo cual es malo porque no podemos usar la API de administración y peor porque a menudo daña la API de administración de tal manera que no se iniciará correctamente nuevamente hasta que reiniciemos todo el clúster como en la primera bala.

La mayoría de las personas que padecen problemas similares los resuelven actualizando a RabbitMQ 3.*. No tenemos el tiempo, el permiso ni la autorización de tiempo de inactividad para un proyecto de este tipo. Incluso ante interrupciones periódicas de varios minutos de duración cuando reiniciamos el clúster debido a este problema, no estábamos autorizados a realizar la actualización. Es una restricción puramente política, pero una realidad desafortunada.

Pregunta:

Dado que no podemos actualizar RabbitMQ en un futuro cercano y que necesitamos continuar usando la API de administración, ¿cómo podemos resolver el problema de las conexiones persistentes y obsoletas que causan fallas en el clúster de mensajería?

Tenemos la capacidad de desarrollar código de cliente nuevo/diferente y ejecutar trabajos en los propios servidores de mensajería, pero no tenemos la capacidad de usarlo rabbitmqctllocalmente o a través sshde ninguna de las máquinas cliente.

Lo que hemos probado:

  • Hemos intentado cambiar las bibliotecas de clientes AMQP con la esperanza de que un mejor cliente se limpie y no deje conexiones obsoletas, sin éxito. El problema persiste.
  • Hemos intentado jugar con la configuración TCP tcp_keepalivey exit_on_closeen los propios servidores RabbitMQ. Ninguna combinación de estos valores resuelve el problema.
  • Hemos creado un script que itera sobre todas las conexiones devueltas por la lista de conexiones de la API JSON y envía un DELETE para cada una que ha estado abierta durante más tiempo del necesario si se estuviera utilizando. Todas estas solicitudes se encuentran con 500 errores del servidor, como se describe en la pregunta SO vinculada anteriormente.

Respuesta1

Sigues reiniciando todo periódicamente.

La otra opción es actualizar la solución de 3.x a su versión actual, pero si no se le permite actualizar, probablemente tampoco se le permitirá hacerlo. Y es casi seguro que será mucho más trabajo que actualizar, especialmente si el código RabbitMQ ha sido refactorizado significativamente.

Hasta que puedas cambiar elpolíticade la situación, esas son tus opciones.

información relacionada