Diseño y denominación de colas.

Algunas reglas sobre cómo organizar puntos, colas y cómo nombrarlos correctamente para que sea más conveniente.

| exchange | type | binding_queue | binding_key | |-------------------------------------------------------| | user.write | topic | user.created.app2 | user.created | 

Los conceptos
AMQP (Advanced Message Queuing Protocol) es un protocolo abierto para transferir mensajes entre componentes del sistema.
Proveedor (Editores / Productor): un programa que envía mensajes.
Suscriptor (consumidor): un programa que acepta mensajes. Por lo general, el suscriptor está en estado de espera de mensajes.
Cola : una cola de mensajes.
Punto de intercambio (Exchange): el punto de intercambio inicial de la cola, que se dedica al enrutamiento.

Regla 1


Cada cola debe representar solo un tipo de trabajo. No mezcle diferentes tipos de mensajes en la misma cola. Y cuando se respeta esta regla, podemos nombrar claramente la cola de tareas que se les presenta.

Regla 2


Evite volver a enviar mensajes a la cola. Si descubre que su suscriptor está intentando reenviar cualquier mensaje a otras colas sin un procesamiento real, lo más probable es que algo no esté diseñado correctamente. El enrutamiento es responsabilidad de los puntos de intercambio, no de las colas.

Regla 3


Los proveedores no necesitan saber nada sobre colas. Una de las ideas principales de AMQP es la división de responsabilidades entre los puntos y las colas, para que los proveedores no tengan que preocuparse de que el mensaje llegue al suscriptor.

Ejemplos y soluciones.


Suponga que desea diseñar puntos y colas para eventos de registro relacionados "personalizados". Los eventos de grabación se activarán en una o más aplicaciones, y estos mensajes serán utilizados por otras aplicaciones.

 | object | event | |------------------| | user | created | | user | updated | | user | deleted | 

La primera pregunta que generalmente se hace son los diversos eventos de un objeto (el objeto "usuario" en este ejemplo), ¿debería usarse un punto de intercambio para publicar los tres eventos, o deberían usarse 3 puntos separados para cada evento? ¿O, en resumen, un punto de intercambio o muchos?

Antes de responder esta pregunta, quiero hacer otra pregunta: ¿realmente necesitamos un punto separado para este caso? ¿Qué pasa si abstraemos los 3 tipos de eventos como un evento de "escritura" cuyos subtipos son "creados", "actualizados" y "eliminados"?

 | object | event | sub-type | |-----------------------------| | user | write | created | | user | write | updated | | user | write | deleted | 

Solución 1


La solución más simple es crear la cola "user.write" y publicar todos los mensajes de los eventos de grabación del usuario en esta cola a través del punto de intercambio global.

Decisión 2


La solución más simple no puede funcionar cuando hay una segunda aplicación (que tiene una lógica de procesamiento diferente) que desea suscribirse a cualquier mensaje publicado en la cola. Cuando se firman varias aplicaciones, al menos necesitamos un punto con el tipo "fanout" con enlaces a varias colas. Por lo tanto, los mensajes se envían al punto y los duplica en cada cola. Cada cola representa un trabajo de procesamiento para cada aplicación.

 | queue | subscriber | |-------------------------------| | user.write.app1 | app1 | | user.write.app2 | app2 | | exchange | type | binding_queue | |---------------------------------------| | user.write | fanout | user.write.app1 | | user.write | fanout | user.write.app2 | 

La segunda solución funciona bien si cada suscriptor realmente quiere manejar todos los subtipos de eventos "user.write". Por ejemplo, si la aplicación del suscriptor está diseñada para simplemente almacenar un registro de transacciones.

Por otro lado, no es muy bueno cuando algunos suscriptores están fuera de su organización y desea notificarles solo de ciertos eventos específicos, por ejemplo, app2 debería recibir un mensaje sobre la creación del usuario y no debería saber sobre eventos de actualización y eliminación.

Decisión 3


Para resolver el problema anterior, debemos extraer el evento "user.created" del tipo "user.write". Un punto de intercambio con un tipo de tema puede ayudarnos. Al publicar mensajes, usaremos user.created / user.updated / user.deleted como claves de enrutamiento en un punto, para que podamos poner la clave de comunicación "user. *" En la cola "user.write.app1" y la clave de comunicación "user.created" en la cola "user.created.app2".

 | queue | subscriber | |---------------------------------| | user.write.app1 | app1 | | user.created.app2 | app2 | | exchange | type | binding_queue | binding_key | |-------------------------------------------------------| | user.write | topic | user.write.app1 | user.* | | user.write | topic | user.created.app2 | user.created | 

Decisión 4


El tipo de tema de tema del punto de intercambio es más flexible en caso de que haya potencialmente más tipos de eventos. Pero si conoce claramente el número exacto de eventos, también puede usar el tipo "directo" para mejorar el rendimiento.

 | queue | subscriber | |---------------------------------| | user.write.app1 | app1 | | user.created.app2 | app2 | | exchange | type | binding_queue | binding_key | |--------------------------------------------------------| | user.write | direct | user.write.app1 | user.created | | user.write | direct | user.write.app1 | user.updated | | user.write | direct | user.write.app1 | user.deleted | | user.write | direct | user.created.app2 | user.created | 

Volvemos a la pregunta "¿un punto o mucho?". Mientras todas las soluciones usen solo un punto, funciona bien, nada malo. ¿En qué situaciones podemos necesitar varios puntos?

Decisión 5


Veamos un ejemplo cuando, además de los eventos creados, actualizados y eliminados descritos anteriormente, tenemos otro grupo de eventos: entrada y salida, un grupo de eventos que describe el "comportamiento del usuario" en lugar de la "grabación de datos". Para diferentes grupos de eventos, se pueden requerir estrategias de enrutamiento completamente diferentes y acuerdo sobre las claves y los nombres de las colas, y para esto, se necesitan puntos de intercambio separados.

 | queue | subscriber | |----------------------------------| | user.write.app1 | app1 | | user.created.app2 | app2 | | user.behavior.app3 | app3 | | exchange | type | binding_queue | binding_key | |--------------------------------------------------------------| | user.write | topic | user.write.app1 | user.* | | user.write | topic | user.created.app2 | user.created | | user.behavior | topic | user.behavior.app3 | user.* | 

Traducción gratuita del artículo RabbitMQ Exchange y Queue Design Trade-off .

Source: https://habr.com/ru/post/443722/


All Articles