Directo vs. Tópico vs. Fanout: Cómo elegir el tipo de intercambio adecuado
Elige intercambios directo, tópico o fanout de RabbitMQ según enrutamiento exacto, enrutamiento con comodines o entrega por difusión.
Directo vs. Tópico vs. Fanout: Cómo elegir el tipo de intercambio adecuado
El tipo de intercambio de RabbitMQ controla a dónde van tus mensajes después de que un productor los publique. Elegir el intercambio incorrecto puede llevar a difundir trabajo privado, perder mensajes con claves de enrutamiento no coincidentes o codificar reglas de enrutamiento que se vuelvan difíciles de mantener más adelante.
La elección práctica es simple: usa direct para enrutamiento exacto, fanout para difusión y topic para enrutamiento con comodines en un esquema de nombres.
Cómo funciona el enrutamiento en RabbitMQ
Un productor publica en un intercambio, no directamente en una cola. El intercambio compara la clave de enrutamiento del mensaje con los enlaces de las colas y luego enruta el mensaje según el tipo de intercambio.
Tres términos importantes:
- Intercambio: recibe los mensajes publicados.
- Cola: almacena mensajes hasta que los consumidores los reciben.
- Enlace: conecta una cola a un intercambio, a veces con una clave de enlace.
Si ninguna cola coincide y el mensaje no está marcado como mandatory, RabbitMQ puede descartar el mensaje no enrutable. Para flujos importantes, usa confirmaciones de publicación y maneja los mensajes devueltos.
Intercambio directo
Un intercambio directo enruta un mensaje a las colas cuya clave de enlace coincide exactamente con la clave de enrutamiento del mensaje.
Úsalo cuando las opciones de enrutamiento sean conocidas y precisas. Buenos ejemplos incluyen severidad de registros, tipo de tarea o colas específicas de inquilinos donde los nombres exactos son suficientes.
Por ejemplo, enlaza error_queue con error y info_queue con info. Un mensaje publicado con la clave de enrutamiento error va a error_queue; un mensaje con info va a info_queue. Si dos colas se enlazan con error, ambas reciben una copia. Los consumidores en la misma cola aún compiten por los mensajes de esa cola.
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='logs_direct', exchange_type='direct')
channel.basic_publish(
exchange='logs_direct',
routing_key='error',
body=b'Conexión a base de datos fallida'
)
connection.close()
Elige directo cuando tus claves de enrutamiento sean estables y no necesites coincidencias con comodines.
Intercambio fanout
Un intercambio fanout enruta cada mensaje a todas las colas enlazadas al intercambio. Ignora la clave de enrutamiento.
Úsalo para eventos de difusión donde cada suscriptor debe recibir el mismo mensaje. Casos comunes incluyen invalidación de caché, eventos de perfil de usuario actualizado, notificaciones de despliegue o actualizaciones de estado en tiempo real.
Por ejemplo, un intercambio fanout user_updates podría alimentar tres colas: email_queue, search_index_queue y analytics_queue. Una actualización de perfil publicada llega a los tres servicios.
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='user_updates', exchange_type='fanout')
channel.basic_publish(
exchange='user_updates',
routing_key='',
body=b'El usuario 123 cambió su nombre de pantalla'
)
connection.close()
Elige fanout cuando la lógica de enrutamiento no importe y cada cola enlazada deba recibir una copia.
Intercambio tópico
Un intercambio tópico enruta mediante la coincidencia de claves de enrutamiento separadas por puntos con claves de enlace con comodines. Te da un enrutamiento flexible sin crear un intercambio diferente para cada tipo de evento.
Los enlaces de tópico usan dos comodines:
*coincide exactamente con una palabra.#coincide con cero o más palabras.
Por ejemplo, con claves de enrutamiento como order.created.us y order.cancelled.eu:
order.*.uscoincide con una acción para pedidos de EE. UU.order.created.#coincide con pedidos creados en todas las regiones y palabras adicionales opcionales.#.eucoincide con eventos que terminan eneu.
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='events_topic', exchange_type='topic')
channel.basic_publish(
exchange='events_topic',
routing_key='order.created.us',
body=b'Pedido 9001 creado'
)
connection.close()
Elige tópico cuando los consumidores necesiten subconjuntos filtrados de un flujo de eventos más grande, como servicio.entorno.severidad, entidad.accion.region o inquilino.evento.prioridad.
Guía rápida de elección
| Necesidad | Tipo de intercambio | Ejemplo |
|---|---|---|
| Enrutamiento de coincidencia exacta | Directo | error, invoice.created |
| Difusión a cada suscriptor | Fanout | evento de purga de caché |
| Enrutamiento con comodines | Tópico | orders.*.us, logs.# |
Evita usar un intercambio tópico como vertedero de claves de enrutamiento inconsistentes. Elige una convención de nombres temprano, documéntala y mantén las palabras ordenadas de lo general a lo específico o de entidad a acción, según cómo filtren tus consumidores.
Conclusión
Usa intercambios directos para destinos exactos, intercambios fanout para difusión e intercambios tópicos cuando los consumidores necesiten filtros con comodines. Si puedes describir la ruta como una etiqueta exacta, usa directo. Si todos necesitan el mensaje, usa fanout. Si los suscriptores necesitan patrones, usa tópico.