Direct vs. Topic vs. Fanout: Den richtigen Exchange-Typ wählen
Wählen Sie RabbitMQ Direct-, Topic- oder Fanout-Exchanges basierend auf exaktem Routing, Wildcard-Routing oder Broadcast-Zustellung.
Direct vs. Topic vs. Fanout: Den richtigen Exchange-Typ wählen
Der Exchange-Typ in RabbitMQ bestimmt, wohin Ihre Nachrichten gelangen, nachdem ein Produzent sie veröffentlicht hat. Wählen Sie den falschen Exchange und Sie könnten private Arbeiten ausstrahlen, Nachrichten mit nicht übereinstimmenden Routing-Keys verlieren oder Routing-Regeln fest codieren, die später schmerzhaft werden.
Die praktische Wahl ist einfach: Verwenden Sie direct für exaktes Routing, fanout für Broadcast und topic für Wildcard-Routing über ein Benennungsschema.
Wie RabbitMQ-Routing funktioniert
Ein Produzent veröffentlicht an einen Exchange, nicht direkt an eine Queue. Der Exchange vergleicht den Nachrichten-Routing-Key mit Queue-Bindungen und leitet die Nachricht dann gemäß dem Exchange-Typ weiter.
Drei Begriffe sind wichtig:
- Exchange: empfängt veröffentlichte Nachrichten.
- Queue: speichert Nachrichten, bis Verbraucher sie empfangen.
- Binding: verbindet eine Queue mit einem Exchange, manchmal mit einem Binding-Key.
Wenn keine Queue übereinstimmt und die Nachricht nicht als mandatory markiert ist, kann RabbitMQ die nicht routbare Nachricht verwerfen. Verwenden Sie für wichtige Abläufe Publisher Confirms und behandeln Sie zurückgesendete Nachrichten.
Direct Exchange
Ein Direct Exchange leitet eine Nachricht an Queues weiter, deren Binding-Key exakt mit dem Nachrichten-Routing-Key übereinstimmt.
Verwenden Sie ihn, wenn die Routing-Entscheidungen bekannt und präzise sind. Gute Beispiele sind Log-Schweregrade, Aufgabentypen oder mandantenspezifische Queues, bei denen exakte Namen ausreichen.
Zum Beispiel binden Sie error_queue mit error und info_queue mit info. Eine mit dem Routing-Key error veröffentlichte Nachricht geht an error_queue; eine mit info an info_queue. Wenn zwei Queues mit error binden, erhalten beide Queues eine Kopie. Verbraucher auf derselben Queue konkurrieren weiterhin um Nachrichten aus dieser Queue.
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'Datenbankverbindung fehlgeschlagen'
)
connection.close()
Wählen Sie Direct, wenn Ihre Routing-Keys stabil sind und Sie kein Wildcard-Matching benötigen.
Fanout Exchange
Ein Fanout Exchange leitet jede Nachricht an jede Queue weiter, die an den Exchange gebunden ist. Er ignoriert den Routing-Key.
Verwenden Sie ihn für Broadcast-Ereignisse, bei denen jeder Abonnent dieselbe Nachricht erhalten soll. Häufige Fälle sind Cache-Invalidierung, Ereignisse zu aktualisierten Benutzerprofilen, Bereitstellungsbenachrichtigungen oder Echtzeit-Statusaktualisierungen.
Zum Beispiel könnte ein user_updates Fanout Exchange drei Queues speisen: email_queue, search_index_queue und analytics_queue. Ein veröffentlichtes Profil-Update erreicht alle drei Dienste.
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'Benutzer 123 hat seinen Anzeigenamen geändert'
)
connection.close()
Wählen Sie Fanout, wenn die Routing-Logik keine Rolle spielt und jede gebundene Queue eine Kopie erhalten soll.
Topic Exchange
Ein Topic Exchange routet durch Abgleich von punktgetrennten Routing-Keys mit Wildcard-Binding-Keys. Er bietet flexibles Routing, ohne für jeden Ereignistyp einen anderen Exchange erstellen zu müssen.
Topic-Bindungen verwenden zwei Wildcards:
*entspricht genau einem Wort.#entspricht null oder mehr Wörtern.
Zum Beispiel mit Routing-Keys wie order.created.us und order.cancelled.eu:
order.*.usentspricht einer Aktion für US-Bestellungen.order.created.#entspricht erstellten Bestellungen in allen Regionen und optionalen zusätzlichen Wörtern.#.euentspricht Ereignissen, die aufeuenden.
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'Bestellung 9001 erstellt'
)
connection.close()
Wählen Sie Topic, wenn Verbraucher gefilterte Teilmengen eines größeren Ereignisstroms benötigen, wie z.B. service.environment.severity, entity.action.region oder tenant.event.priority.
Kurze Entscheidungshilfe
| Bedarf | Exchange-Typ | Beispiel |
|---|---|---|
| Exaktes Match-Routing | Direct | error, invoice.created |
| Broadcast an jeden Abonnenten | Fanout | Cache-Purge-Ereignis |
| Wildcard-Routing | Topic | orders.*.us, logs.# |
Vermeiden Sie es, einen Topic Exchange als Ablage für inkonsistente Routing-Keys zu verwenden. Wählen Sie frühzeitig eine Namenskonvention, dokumentieren Sie sie und halten Sie die Wörter von breit zu spezifisch oder von Entität zu Aktion geordnet, je nachdem, wie Ihre Verbraucher filtern.
Fazit
Verwenden Sie Direct Exchanges für exakte Ziele, Fanout Exchanges für Broadcast und Topic Exchanges, wenn Verbraucher Wildcard-Filter benötigen. Wenn Sie die Route als ein exaktes Label beschreiben können, verwenden Sie Direct. Wenn jeder die Nachricht benötigt, verwenden Sie Fanout. Wenn Abonnenten Muster benötigen, verwenden Sie Topic.