Direct vs. Topic vs. Fanout: Scegliere il Tipo di Exchange Corretto

Scegli gli exchange RabbitMQ direct, topic o fanout in base al routing esatto, al routing con wildcard o alla consegna broadcast.

Direct vs. Topic vs. Fanout: Scegliere il Tipo di Exchange Corretto

Il tipo di exchange di RabbitMQ controlla dove vanno i tuoi messaggi dopo che un produttore li pubblica. Scegliere l'exchange sbagliato può portare a trasmettere lavoro privato, perdere messaggi con chiavi di routing non corrispondenti o codificare regole di routing che diventano difficili da gestire in seguito.

La scelta pratica è semplice: usa direct per il routing esatto, fanout per la trasmissione broadcast e topic per il routing con wildcard attraverso uno schema di denominazione.

Come Funziona il Routing in RabbitMQ

Un produttore pubblica su un exchange, non direttamente su una coda. L'exchange confronta la chiave di routing del messaggio con i binding delle code, quindi instrada il messaggio in base al tipo di exchange.

Tre termini sono importanti:

  • Exchange: riceve i messaggi pubblicati.
  • Coda: memorizza i messaggi finché i consumatori non li ricevono.
  • Binding: collega una coda a un exchange, a volte con una chiave di binding.

Se nessuna coda corrisponde e il messaggio non è contrassegnato come mandatory, RabbitMQ può eliminare il messaggio non instradabile. Per flussi importanti, utilizza le conferme del publisher e gestisci i messaggi restituiti.

Exchange Direct

Un exchange direct instrada un messaggio verso code la cui chiave di binding corrisponde esattamente alla chiave di routing del messaggio.

Usalo quando le scelte di routing sono note e precise. Buoni esempi includono la severità dei log, il tipo di attività o code specifiche per tenant dove i nomi esatti sono sufficienti.

Ad esempio, collega error_queue con error e info_queue con info. Un messaggio pubblicato con chiave di routing error va a error_queue; un messaggio con info va a info_queue. Se due code si legano con error, entrambe ricevono una copia. I consumatori sulla stessa coda competono comunque per i messaggi di quella coda.

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'Connessione al database fallita'
)

connection.close()

Scegli direct quando le tue chiavi di routing sono stabili e non hai bisogno di corrispondenza con wildcard.

Exchange Fanout

Un exchange fanout instrada ogni messaggio verso tutte le code collegate all'exchange. Ignora la chiave di routing.

Usalo per eventi broadcast dove ogni sottoscrittore deve ricevere lo stesso messaggio. Casi comuni includono invalidazione della cache, eventi di aggiornamento del profilo utente, notifiche di deployment o aggiornamenti di stato in tempo reale.

Ad esempio, un exchange fanout user_updates potrebbe alimentare tre code: email_queue, search_index_queue e analytics_queue. Un aggiornamento del profilo pubblicato raggiunge tutti e tre i servizi.

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'L\'utente 123 ha cambiato il proprio nome visualizzato'
)

connection.close()

Scegli fanout quando la logica di routing non è importante e ogni coda collegata deve ricevere una copia.

Exchange Topic

Un exchange topic instrada confrontando chiavi di routing separate da punti con chiavi di binding con wildcard. Offre un routing flessibile senza creare un exchange diverso per ogni tipo di evento.

I binding topic utilizzano due wildcard:

  • * corrisponde esattamente a una parola.
  • # corrisponde a zero o più parole.

Ad esempio, con chiavi di routing come order.created.us e order.cancelled.eu:

  • order.*.us corrisponde a un'azione per ordini USA.
  • order.created.# corrisponde a ordini creati in tutte le regioni e parole aggiuntive opzionali.
  • #.eu corrisponde a eventi che terminano con eu.
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'Ordine 9001 creato'
)

connection.close()

Scegli topic quando i consumatori hanno bisogno di sottoinsiemi filtrati di un flusso di eventi più ampio, come service.environment.severity, entity.action.region o tenant.event.priority.

Guida Rapida alla Scelta

Necessità Tipo di exchange Esempio
Routing con corrispondenza esatta Direct error, invoice.created
Trasmissione a ogni sottoscrittore Fanout evento di svuotamento cache
Routing con wildcard Topic orders.*.us, logs.#

Evita di usare un exchange topic come deposito per chiavi di routing inconsistenti. Scegli una convenzione di denominazione all'inizio, documentala e mantieni le parole ordinate dal generale allo specifico o dall'entità all'azione, a seconda di come i tuoi consumatori filtrano.

Conclusione

Usa exchange direct per destinazioni esatte, exchange fanout per trasmissioni broadcast e exchange topic quando i consumatori hanno bisogno di filtri con wildcard. Se puoi descrivere la rotta come un'unica etichetta esatta, usa direct. Se tutti hanno bisogno del messaggio, usa fanout. Se gli abbonati hanno bisogno di pattern, usa topic.