2009-08-28 11 views
17

Estoy probando RabbitMQ con this enlace de pitón.¿Cómo configurar la detección de tiempo de espera en un servidor RabbitMQ?

Una cosa que noté es que si mato imprudentemente a un consumidor (emulando un programa bloqueado), el servidor pensará que este consumidor todavía está allí por un largo tiempo. El resultado de esto es que cualquier otro mensaje será ignorado.

Por ejemplo, si mata a un consumidor 1 vez y lo vuelve a conectar, se ignorarán 1/2 mensajes. Si mata a otro consumidor, se ignorarán 2/3 mensajes. Si matas a un tercero, entonces se ignorarán 3/4 mensajes, y así sucesivamente.

He intentado activar los reconocimientos, pero no parece estar ayudando. La única solución que he encontrado es detener manualmente el servidor y restablecerlo.

¿Hay una manera mejor?

cómo volver a crear este escenario

  • Run RabbitMQ.

  • Desarchivar this library.

  • Descargue el consumidor y el editor here. Ejecute amqp_consumer.py dos veces. Ejecute amqp_publisher.py, agregue algunos datos y observe que funciona como se esperaba. Los mensajes se reciben al estilo de todos contra todos.

  • Mata uno de los procesos del consumidor con kill -9 o administrador de tareas.

  • Ahora cuando publique un mensaje, se perderá el 50% de los mensajes.

+0

He actualizado mi respuesta. –

+0

No puedo reproducir esto. ¿Qué versión de Linux estaba usando? –

+3

Buena pregunta: este es un problema crítico si se ejecuta detrás de un cortafuegos o un dispositivo de equilibrio de carga IP que suelta conexiones inactivas después de N segundos, porque ni RabbitMQ ni el cliente serán informados de que el socket se ha ido lejos hasta que intenten usarlo. –

Respuesta

2

Proporcione algunos detalles más sobre los componentes que ha declarado. Por lo general (e independiente de la aplicación cliente) una cola con las propiedades

  • exclusivos y
  • auto-eliminar

hay que dejarse eliminado tan pronto como la conexión entre el cliente declara y el corredor se rompe. Sin embargo, esto no te ayudará con las colas compartidas. Detalla un poco qué es exactamente lo que estás tratando de modelar.

+0

No estoy hablando de cuándo se eliminan las colas. Estoy hablando de cómo rabbitmq no detecta conexiones bloqueadas durante mucho tiempo y sigue tratando de enviar mensajes como si todavía estuvieran allí. – Unknown

5

RabbitMQ no tiene un tiempo de espera en los reconocimientos del cliente de que se ha procesado un mensaje: consulte this post (puede que todo el tema sea de su interés). Algunos puntos sobresalientes de la publicación:

El modelo AMQP ack para las suscripciones y "pull" son idénticos. En ambos casos el mensaje se mantiene en el servidor pero no está disponible para otros consumidores hasta que ha sido ack'ed (y se elimina), nack'ed (con básico.rechazar; aunque RabbitMQ no implementa eso) o el canal/conexión está cerrado (en el cual punto el mensaje está disponible a otros consumidores).

y (mi énfasis)

No hay tiempo de espera en espera de acks. Por lo general, esto no es un problema ya que los casos comunes de un acuse de recibo faltante - la red o el fracaso cliente - dará lugar a la conexión conseguir cayó (y así activar el comportamiento descrito anteriormente). Aún así, un tiempo de espera podría ser útil para, por ejemplo, lidiar con con vida pero que no responde consumidores. Eso ha surgido en la discusión antes. ¿Existe un caso de uso específico de que tenga en cuenta que requiere tal funcionalidad?

El problema bien podría deberse a que en un modelo de extracción de cliente, es más difícil para que el servidor detecta una conexión rota (en contraposición a un consumidor con vida, pero no responde), especialmente en lo que el servidor parece dispuesto a esperar por siempre por un ack.

Actualización: En Linux, puede adjuntar manejadores de señal para SIGTERM y/o SIGKILL y/o SIGINT y, con suerte, cerrar la conexión de forma ordenada desde el cliente. En Windows, creo que el cierre del Administrador de tareas invoca la API de Win32 TerminateProcess, sobre el cual MSDN dice:

Si un proceso está terminado por TerminateProcess, todos los subprocesos del proceso se terminan inmediatamente sin posibilidad de ejecutar código adicional Esto significa que el hilo no ejecuta el código en los controladores controladores de terminación. Además, no se adjunta DLL se notifica que el proceso es desprendimiento.

Esto significa que puede ser difícil detectar la terminación y cerrarla de forma ordenada.

Puede valer la pena seguir en la lista de RabbitMQ con su propio caso de uso para un tiempo de espera de ack.

+0

De acuerdo con esa lista de correo, si el consumidor termina la conexión, debería funcionar correctamente. Sin embargo, kill -9 o el proceso final en taskmanager también debe terminar la conexión de esa manera. Pero todavía no funciona correctamente. – Unknown

11

No veo amqp_consumer.py o amqp_producer.py en el tarball, por lo que reproducir el error es complicado.

RabbitMQ finaliza las conexiones, liberando sus mensajes no reconocidos para su reentrega a otros clientes, siempre que el sistema operativo indique que se ha cerrado un socket. Sus síntomas son muy extraños, ya que incluso un kill -9 debería hacer que el zócalo TCP se limpie correctamente.

Algunas personas han notado problemas con los sockets que sobreviven más de lo que deberían cuando se ejecutan con un firewall o dispositivo NAT entre los clientes de AMQP y el servidor. ¿Podría ser un problema aquí, o está ejecutando todo en localhost? Además, ¿en qué sistema operativo está ejecutando los diversos componentes del sistema?

ETA: De su comentario a continuación, supongo que mientras ejecuta el servidor en Linux, puede ejecutar los clientes en Windows. Si este es el caso, podría ser que el controlador TCP de Windows no cierre correctamente los sockets, que es diferente del comportamiento kill-9 en Unix. (En Unix, el núcleo se cerrará correctamente las conexiones TCP en cualquier proceso matado.)

Si ese es el caso, entonces el malas noticias es que RabbitMQ sólo puede liberar recursos cuando se cierra el conector, por lo que si el cliente el sistema operativo no hace eso, no hay nada que pueda hacer. Esto es lo mismo que casi todos los demás servicios basados ​​en TCP que existen.

La buenas noticias, sin embargo, es que AMQP admite una opción de "latido" para exactamente estos casos, donde el tejido de red no es confiable. Podría intentar habilitar los latidos del corazón. Cuando están habilitados, si el servidor no recibe ningún tráfico dentro de un intervalo configurable, decide que la conexión debe estar muerta.

La malas noticias, sin embargo, es que no creo que py-amqplib sea compatible con los latidos del corazón en este momento. Vale la pena intentarlo, sin embargo!

+0

Lo siento. El productor y el consumidor están aquí http://blogs.digitar.com/jjww/code-samples/ – Unknown

+0

Estoy ejecutando rabbitmq en un servidor remoto de Linux mientras estoy ejecutando el productor y el consumidor. Me doy cuenta de que el zócalo puede no haber sido cerrado limpiamente, pero eso es exactamente lo que quiero emular. Estuve probando para ver cómo rabbitmq maneja los procesos bloqueados que pueden no haber cerrado el socket limpiamente, y desafortunadamente no parece manejar esto muy bien. – Unknown

+1

@ Tony; ¿cómo se habilita la opción de "latido" dentro del servidor RabbitMQ (dentro de /etc/rabbitmq/rabbitmq.config, por ejemplo)? –

Cuestiones relacionadas