RabbitMQ y relación entre canal y conexión

176

El cliente Java RabbitMQ tiene los siguientes conceptos:

  • Connection - una conexión a una instancia de servidor RabbitMQ
  • Channel - ???
  • Grupo de subprocesos del consumidor: un grupo de subprocesos que consumen mensajes fuera de las colas del servidor RabbitMQ
  • Cola: una estructura que contiene mensajes en orden FIFO

Estoy tratando de entender la relación y , lo que es más importante , las asociaciones entre ellos.

  1. Todavía no estoy muy seguro de qué Channeles, aparte del hecho de que esta es la estructura que publica y consume, y que se crea a partir de una conexión abierta. Si alguien pudiera explicarme lo que representa el "Canal", podría ayudar a aclarar algunas cosas.
  2. ¿Cuál es la relación entre Channel y Queue? ¿Se puede usar el mismo canal para comunicarse con múltiples colas, o tiene que ser 1: 1?
  3. ¿Cuál es la relación entre Queue y Consumer Pool? ¿Se pueden suscribir múltiples consumidores a la misma cola? ¿Pueden ser consumidas múltiples colas por el mismo consumidor? ¿O es la relación 1: 1?

Gracias de antemano por cualquier ayuda aquí!


fuente
Las respuestas a esta pregunta me llevaron a informar este problema con el cliente de Golang en lugar de hacer la pregunta aquí.
Bruce Adams
El canal es un concepto lógico utilizado para multiplexar una única conexión TCP física entre un cliente y un nodo. El número de canal se incluye en el encabezado del mensaje de la trama AMQP.
ymas

Respuestas:

196
  1. A Connectionrepresenta una conexión TCP real con el intermediario de mensajes, mientras que a Channeles una conexión virtual (conexión AMQP) dentro de él. De esta manera, puede usar tantas conexiones (virtuales) como desee dentro de su aplicación sin sobrecargar el intermediario con conexiones TCP.

  2. Puedes usar uno Channelpara todo. Sin embargo, si tiene varios subprocesos, se sugiere utilizar uno diferente Channelpara cada subproceso.

    Seguridad de subprocesos de canal en la Guía de API de cliente Java :

    Las instancias de canal son seguras para su uso por múltiples subprocesos. Las solicitudes en un canal se serializan, y solo un subproceso puede ejecutar un comando en el canal a la vez. Aun así, las aplicaciones deberían preferir usar un canal por hilo en lugar de compartir el mismo canal en varios hilos.

    No hay una relación directa entre Channely Queue. A Channelse utiliza para enviar comandos AMQP al intermediario. Esto puede ser la creación de una cola o similar, pero estos conceptos no están unidos.

  3. Cada uno se Consumerejecuta en su propio subproceso asignado desde el grupo de subprocesos del consumidor. Si se suscriben varios consumidores a la misma cola, el corredor utiliza round-robin para distribuir los mensajes entre ellos por igual. Ver Tutorial dos: "Colas de trabajo" .

    También es posible adjuntar lo mismo Consumera múltiples colas. Puede entender a los consumidores como devoluciones de llamada. Se llaman cada vez que llega un mensaje a una Cola a la que está obligado el Consumidor. Para el caso del Cliente Java, cada Consumidor tiene un método handleDelivery(...), que representa el método de devolución de llamada. Lo que normalmente haces es subclasificar DefaultConsumery anular handleDelivery(...). Nota: Si adjunta la misma instancia de Consumer a varias colas, este método será llamado por diferentes hilos. Así que cuide la sincronización si es necesario.

Bengt
fuente
44
Solo para agregar de la documentación: las devoluciones de llamadas a los consumidores se envían en un hilo separado del hilo administrado por Connection. Esto significa que los consumidores pueden llamar de forma segura a los métodos de bloqueo en Connection o Channel, como queueDeclare, txCommit, basicCancel o basicPublish. Cada canal tiene su propio hilo de despacho. Para el caso de uso más común de un Consumidor por Canal, esto significa que los Consumidores no retienen a otros Consumidores. Si tiene varios consumidores por canal, tenga en cuenta que un consumidor de larga duración puede retrasar el envío de devoluciones de llamadas a otros consumidores en ese canal.
filip
1
Si adjunta la misma instancia de Consumidor a múltiples Colas del mismo Canal, eso significaría que las devoluciones de llamada se envían en el mismo hilo. En ese caso, no necesitarías sincronización, ¿verdad?
filip
¿Puedo usar solo una conexión y usar un grupo de canales en lugar de un grupo de conexiones? ¿Esto afectará el rendimiento de publicación de mensajes?
qeek
44
Creo que esta referencia a la API del cliente Java ahora está desactualizada y, de hecho, la referencia de hoy contradice directamente la cita en esta respuesta. La referencia de hoy dice "Las instancias de canal no deben compartirse entre hilos".
Edwin Dalorzo el
1
@EdwinDalorzo: parece que quien escribió originalmente la documentación no entendió completamente la dicotomía de conexión de canales. La arquitectura fundamental de AMQP 0.9.1 realmente trata un canal como una sesión, por lo que diferentes hilos que comparten una sesión realmente no tiene sentido. Supongo que esa es la razón del cambio.
theMayer
53

Aquí es útil una buena comprensión conceptual de lo que hace el protocolo AMQP "bajo el capó". Ofrecería que la documentación y la API que AMQP 0.9.1 eligió implementar hace que esto sea particularmente confuso, por lo que la pregunta en sí es una con la que muchas personas tienen que luchar.

TL; DR

Una conexión es el socket TCP físico negociado con el servidor AMQP. Los clientes implementados correctamente tendrán uno de estos por aplicación, seguro para subprocesos, compartible entre subprocesos.

Un canal es una sesión de aplicación única en la conexión. Un hilo tendrá una o más de estas sesiones. La arquitectura 0.9.1 de AMQP es que no deben compartirse entre los subprocesos, y deben cerrarse / destruirse cuando el subproceso que lo creó termina con él. El servidor también los cierra cuando se producen varias violaciones de protocolo.

Un consumidor es una construcción virtual que representa la presencia de un "buzón" en un canal en particular. El uso de un consumidor le dice al intermediario que envíe mensajes desde una cola particular a ese punto final del canal.

Datos de conexión

Primero, como otros han señalado correctamente, una conexión es el objeto que representa la conexión TCP real al servidor. Las conexiones se especifican a nivel de protocolo en AMQP, y toda comunicación con el intermediario se realiza a través de una o más conexiones.

  • Como se trata de una conexión TCP real, tiene una dirección IP y un número de puerto.
  • Los parámetros de protocolo se negocian por cliente como parte de la configuración de la conexión (un proceso conocido como protocolo de enlace) .
  • Está diseñado para ser de larga duración ; Hay pocos casos en los que el cierre de la conexión es parte del diseño del protocolo.
  • Desde una perspectiva OSI, probablemente reside en algún lugar alrededor de la Capa 6
  • Los latidos se pueden configurar para monitorear el estado de la conexión, ya que TCP no contiene nada en sí mismo para hacer esto.
  • Es mejor tener un hilo dedicado que administre las lecturas y escrituras en el socket TCP subyacente. La mayoría, si no todos, los clientes de RabbitMQ hacen esto. En ese sentido, generalmente son seguros para subprocesos.
  • Relativamente hablando, las conexiones son "caras" de crear (debido al apretón de manos), pero prácticamente hablando, esto realmente no importa. La mayoría de los procesos realmente solo necesitarán un objeto de conexión. Sin embargo, puede mantener las conexiones en un grupo si encuentra que necesita más rendimiento del que puede proporcionar un solo subproceso / socket (poco probable con la tecnología informática actual).

Datos del canal

Un canal es la sesión de la aplicación que se abre para que cada parte de su aplicación se comunique con el corredor RabbitMQ. Funciona a través de una única conexión y representa una sesión con el intermediario.

  • Como representa una parte lógica de la lógica de la aplicación, cada canal generalmente existe en su propio hilo.
  • Por lo general, todos los canales abiertos por su aplicación compartirán una sola conexión (son sesiones livianas que operan sobre la conexión). Las conexiones son seguras para subprocesos, por lo que está bien.
  • La mayoría de las operaciones de AMQP se realizan a través de canales.
  • Desde la perspectiva de la capa OSI, los canales probablemente estén alrededor de la capa 7 .
  • Los canales están diseñados para ser transitorios ; Parte del diseño de AMQP es que el canal normalmente se cierra en respuesta a un error (por ejemplo, volver a declarar una cola con diferentes parámetros antes de eliminar la cola existente).
  • Como son transitorios, su aplicación no debe agrupar los canales.
  • El servidor usa un número entero para identificar un canal. Cuando el hilo que gestiona la conexión recibe un paquete para un canal en particular, utiliza este número para decirle al agente a qué canal / sesión pertenece el paquete.
  • Los canales generalmente no son seguros para subprocesos, ya que no tendría sentido compartirlos entre subprocesos. Si tiene otro hilo que necesita usar el corredor, se necesita un nuevo canal.

Datos del consumidor

Un consumidor es un objeto definido por el protocolo AMQP. No es un canal ni una conexión, sino que es algo que su aplicación particular utiliza como un "buzón" para colocar mensajes.

  • "Crear un consumidor" significa que usted le dice al corredor (usando un canal a través de una conexión ) que desea que le envíen mensajes a través de ese canal. En respuesta, el corredor registrará que tiene un consumidor en el canal y comenzará a enviarle mensajes.
  • Cada mensaje enviado a través de la conexión hará referencia tanto a un número de canal como a un número de consumidor . De esa manera, el hilo de gestión de la conexión (en este caso, dentro de la API de Java) sabe qué hacer con el mensaje; entonces, el hilo de manejo de canales también sabe qué hacer con el mensaje.
  • La implementación del consumidor tiene la mayor cantidad de variación, porque es literalmente específica de la aplicación. En mi implementación, elegí desviar una tarea cada vez que llegaba un mensaje a través del consumidor; por lo tanto, tenía un hilo que administraba la conexión, un hilo que administraba el canal (y, por extensión, el consumidor) y uno o más hilos de tareas para cada mensaje entregado a través del consumidor.
  • Cerrar una conexión cierra todos los canales en la conexión. Cerrar un canal cierra a todos los consumidores en el canal. También es posible cancelar un consumidor (sin cerrar el canal). Hay varios casos en los que tiene sentido hacer cualquiera de las tres cosas.
  • Por lo general, la implementación de un consumidor en un cliente AMQP asignará un canal dedicado al consumidor para evitar conflictos con las actividades de otros hilos o códigos (incluida la publicación).

En términos de lo que quiere decir con grupo de subprocesos del consumidor, sospecho que el cliente Java está haciendo algo similar a lo que programé para que hiciera mi cliente (el mío se basó en el cliente .Net, pero muy modificado).

theMayer
fuente
1
"los canales no deben agruparse", eso es lo que estoy buscando
ospider
"Dado que son transitorios, la aplicación no debe agrupar los canales". - ¿Puedes aclarar cómo llegaste a esta conclusión, por favor? Los documentos recomiendan la agrupación de canales si la implementación de "un canal por subproceso" está utilizando demasiados recursos, consulte aquí: rabbitmq.com/channels.html#resource-usage
ymas
@ymas: la documentación a la que te refieres es especulativa y, en mi opinión, mala orientación. Estoy leyendo el código fuente y las especificaciones del protocolo. Los canales no se deben agrupar, punto. Además, un canal por hilo es una guía basada en este mismo principio. Si descubre que tiene tantos canales abiertos que el servidor tiene recursos limitados, debe reevaluar su arquitectura (es decir, cambiar a un esquema de alta disponibilidad y / o reducir la concurrencia).
theMayer
21

Encontré este artículo que explica todos los aspectos del modelo AMQP, de los cuales, el canal es uno. Me resultó muy útil para completar mi comprensión.

https://www.rabbitmq.com/tutorials/amqp-concepts.html

Algunas aplicaciones necesitan múltiples conexiones a un corredor AMQP. Sin embargo, no es deseable mantener abiertas muchas conexiones TCP al mismo tiempo porque esto consume recursos del sistema y dificulta la configuración de los firewalls. Las conexiones AMQP 0-9-1 se multiplexan con canales que pueden considerarse "conexiones ligeras que comparten una única conexión TCP".

Para las aplicaciones que usan múltiples hilos / procesos para el procesamiento, es muy común abrir un nuevo canal por hilo / proceso y no compartir canales entre ellos.

La comunicación en un canal en particular está completamente separada de la comunicación en otro canal, por lo tanto, cada método AMQP también lleva un número de canal que los clientes usan para determinar para qué canal es el método (y, por lo tanto, qué controlador de eventos debe invocarse, por ejemplo) .

CamW
fuente
4

Existe una relación entre como una conexión TCP puede tener múltiples canales .

Canal : es una conexión virtual dentro de una conexión. Al publicar o consumir mensajes de una cola, todo se hace a través de un canal. Mientras que Conexión : es una conexión TCP entre su aplicación y el intermediario RabbitMQ.

En la arquitectura de subprocesos múltiples, es posible que necesite una conexión separada por subproceso. Eso puede conducir a una infrautilización de la conexión TCP, también agrega una sobrecarga al sistema operativo para establecer tantas conexiones TCP que requiera durante el tiempo pico de la red. El rendimiento del sistema podría reducirse drásticamente. Aquí es donde el canal resulta útil, crea conexiones virtuales dentro de una conexión TCP. Inmediatamente reduce la sobrecarga del sistema operativo, también nos permite realizar operaciones asincrónicas de una manera más rápida, confiable y simultánea. ingrese la descripción de la imagen aquí

Atul Jain
fuente