Direct vs. Topic vs. Fanout : Choisir le bon type d'échange
Choisissez les échanges RabbitMQ direct, topic ou fanout en fonction du routage exact, du routage par joker ou de la diffusion en broadcast.
Direct vs. Topic vs. Fanout : Choisir le bon type d'échange
Le type d'échange RabbitMQ contrôle où vont vos messages après qu'un producteur les a publiés. Choisir le mauvais échange peut entraîner la diffusion de travaux privés, la perte de messages avec des clés de routage non correspondantes, ou l'encodage en dur de règles de routage qui deviennent pénibles plus tard.
Le choix pratique est simple : utilisez direct pour le routage exact, fanout pour la diffusion, et topic pour le routage par joker sur un schéma de nommage.
Comment fonctionne le routage RabbitMQ
Un producteur publie sur un échange, pas directement sur une file d'attente. L'échange compare la clé de routage du message avec les liaisons des files d'attente, puis achemine le message selon le type d'échange.
Trois termes importants :
- Échange : reçoit les messages publiés.
- File d'attente : stocke les messages jusqu'à ce que les consommateurs les reçoivent.
- Liaison : connecte une file d'attente à un échange, parfois avec une clé de liaison.
Si aucune file d'attente ne correspond et que le message n'est pas marqué mandatory, RabbitMQ peut supprimer le message non routable. Pour les flux importants, utilisez les confirmations de publication et gérez les messages retournés.
Échange Direct
Un échange direct achemine un message vers les files d'attente dont la clé de liaison correspond exactement à la clé de routage du message.
Utilisez-le lorsque les choix de routage sont connus et précis. De bons exemples incluent la sévérité des logs, le type de tâche, ou les files d'attente spécifiques à un locataire où les noms exacts suffisent.
Par exemple, liez error_queue avec error et info_queue avec info. Un message publié avec la clé de routage error va à error_queue ; un message avec info va à info_queue. Si deux files d'attente sont liées avec error, les deux files reçoivent une copie. Les consommateurs sur la même file d'attente se disputent toujours les messages de cette file.
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'Échec de connexion à la base de données'
)
connection.close()
Choisissez direct lorsque vos clés de routage sont stables et que vous n'avez pas besoin de correspondance par joker.
Échange Fanout
Un échange fanout achemine chaque message vers toutes les files d'attente liées à l'échange. Il ignore la clé de routage.
Utilisez-le pour les événements de diffusion où chaque abonné doit recevoir le même message. Les cas courants incluent l'invalidation de cache, les événements de mise à jour de profil utilisateur, les notifications de déploiement, ou les mises à jour de statut en temps réel.
Par exemple, un échange fanout user_updates peut alimenter trois files d'attente : email_queue, search_index_queue, et analytics_queue. Une mise à jour de profil publiée atteint les trois services.
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'utilisateur 123 a changé son nom d'affichage"
)
connection.close()
Choisissez fanout lorsque la logique de routage n'a pas d'importance et que chaque file d'attente liée doit recevoir une copie.
Échange Topic
Un échange topic achemine en faisant correspondre des clés de routage séparées par des points avec des clés de liaison par joker. Il offre un routage flexible sans créer un échange différent pour chaque type d'événement.
Les liaisons topic utilisent deux jokers :
*correspond exactement à un mot.#correspond à zéro ou plusieurs mots.
Par exemple, avec des clés de routage comme order.created.us et order.cancelled.eu :
order.*.uscorrespond à une action pour les commandes américaines.order.created.#correspond aux commandes créées dans toutes les régions et des mots supplémentaires optionnels.#.eucorrespond aux événements se terminant pareu.
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'Commande 9001 créée'
)
connection.close()
Choisissez topic lorsque les consommateurs ont besoin de sous-ensembles filtrés d'un flux d'événements plus large, comme service.environment.severity, entity.action.region, ou tenant.event.priority.
Guide de choix rapide
| Besoin | Type d'échange | Exemple |
|---|---|---|
| Routage par correspondance exacte | Direct | error, invoice.created |
| Diffusion à chaque abonné | Fanout | événement de purge de cache |
| Routage par joker | Topic | orders.*.us, logs.# |
Évitez d'utiliser un échange topic comme un fourre-tout pour des clés de routage incohérentes. Choisissez une convention de nommage tôt, documentez-la, et gardez les mots ordonnés du général au spécifique ou de l'entité à l'action, selon la façon dont vos consommateurs filtrent.
À retenir
Utilisez les échanges direct pour des destinations exactes, les échanges fanout pour la diffusion, et les échanges topic lorsque les consommateurs ont besoin de filtres par joker. Si vous pouvez décrire la route comme une seule étiquette exacte, utilisez direct. Si tout le monde a besoin du message, utilisez fanout. Si les abonnés ont besoin de motifs, utilisez topic.