Quels sont les modèles de messages RabbitMQ courants et quand les utiliser ?
Libérez le potentiel de RabbitMQ en maîtrisant les modèles de messagerie essentiels. Ce guide détaille la structure, les cas d'utilisation et les conseils d'implémentation pour les files d'attente de travail (pour la distribution de tâches et l'équilibrage de charge), Publish/Subscribe (pour la diffusion d'événements système) et Request/Reply (pour simuler des appels synchrones). Découvrez des concepts cruciaux tels que les accusés de réception de messages, la distribution équitable (QoS) et les échanges spécialisés (Fanout, Direct, Topic) pour concevoir des applications hautement évolutives, découplées et fiables à l'aide de RabbitMQ.
Quels sont les modèles de messages RabbitMQ courants et quand les utiliser ?
Les modèles de messages RabbitMQ déterminent si un seul travailleur gère une tâche, si chaque abonné reçoit un événement, ou si un service attend une réponse. Si vous choisissez le mauvais modèle, votre système peut dupliquer le travail, perdre des événements utiles ou bloquer sur des appels qui auraient dû rester asynchrones.
RabbitMQ vous offre des échanges, des files d'attente, des liaisons, des accusés de réception et des propriétés de message. Le travail de conception utile consiste à choisir comment ces éléments s'adaptent à votre application. Les modèles courants sont les files d'attente de travail, Publier/S'abonner, le routage Direct ou Topic, et Demande/Réponse.
Files d'attente de travail : Répartir les tâches entre les travailleurs
Le modèle de file d'attente de travail, souvent appelé file d'attente de tâches, est le modèle de message le plus simple et le plus courant utilisé pour distribuer des tâches chronophages entre plusieurs processus travailleurs (consommateurs).
Comment ça fonctionne
- Un producteur envoie des tâches (messages) à une seule file d'attente.
- Plusieurs consommateurs (travailleurs) écoutent la même file d'attente.
- RabbitMQ délivre chaque message à un seul consommateur, de sorte que les travailleurs se partagent le backlog.
Par défaut, RabbitMQ distribue les messages en tourniquet (round-robin) entre les consommateurs actifs. Cette distribution n'est pas toujours équitable si un travailleur prend des tâches lentes tandis qu'un autre reçoit des tâches rapides, donc vous associez généralement ce modèle avec des accusés de réception et une limite de prélecture.
Utiliser les accusés de réception
Avec les accusés de réception manuels, un travailleur indique à RabbitMQ quand une tâche est terminée. Si le travailleur meurt avant d'envoyer basic_ack, RabbitMQ peut remettre en file d'attente et redistribuer ce message à un autre consommateur. C'est ce qui rend une file d'attente de travail utile pour la génération de rapports, le traitement d'images, les tâches de facturation, ou toute tâche que vous ne voulez pas perdre silencieusement.
Définir un nombre de prélecture
basic.qos contrôle combien de messages non accusés un consommateur peut détenir à la fois. Un prefetch_count de 1 est un point de départ sûr pour des tâches lentes et inégales, car RabbitMQ n'enverra pas une deuxième tâche à ce consommateur tant qu'il n'aura pas accusé réception de la première. Pour des tâches plus rapides, vous pouvez augmenter la valeur après avoir mesuré le débit et l'utilisation mémoire.
Exemple d'implémentation (conceptuel)
# Configuration du consommateur pour une distribution équitable
channel.basic_qos(prefetch_count=1)
channel.basic_consume(queue='task_queue', on_message_callback=worker_function)
# La logique du travailleur doit envoyer un accusé de réception après un traitement réussi
worker_function(ch, method, properties, body):
# Traiter la tâche...
ch.basic_ack(delivery_tag=method.delivery_tag)
Publier/S'abonner : Diffuser des événements
Le modèle Pub/Sub est conçu pour diffuser des messages à plusieurs consommateurs intéressés simultanément. Contrairement aux files d'attente de travail, où chaque message est consommé par un seul travailleur, Pub/Sub garantit que chaque abonné connecté reçoit une copie du message.
Utiliser un échange Fanout
Un producteur publie sur un échange Fanout. L'échange ignore les clés de routage et copie le message dans chaque file d'attente qui lui est liée. Chaque abonné a normalement sa propre file d'attente, donc un service de journalisation, un service de métriques et un service d'audit peuvent tous recevoir le même événement sans entrer en compétition.
Cas d'utilisation
- Notifications en temps réel : Diffuser un événement de mode maintenance à chaque instance d'application.
- Distribution de journaux : Envoyer le même événement de journal à un service d'archivage et à un service d'alerte.
- Invalidation de cache : Demander à toutes les instances de service de vider un cache local après un changement de base de données.
Astuce d'implémentation
Pour les abonnés éphémères, créez une file d'attente exclusive et auto-supprimante et liez-la à l'échange Fanout. Pour les abonnés durables, utilisez une file d'attente durable afin que l'abonné puisse revenir et lire les messages arrivés pendant son absence.
Routage Direct et Topic : Envoyer des événements de manière sélective
Alors que l'échange Fanout offre une diffusion aveugle, AMQP propose des échanges pour une publication sélective, étendant le modèle Pub/Sub.
Échange Direct
Les messages sont routés vers les files d'attente en fonction d'une correspondance exacte entre la clé de routage du message et la clé de liaison de la file d'attente. Ceci est utile lorsque vous devez cibler spécifiquement différents types de consommateurs.
Par exemple, votre éditeur de journaux peut envoyer des messages avec des clés de routage comme error, warning et info. Une file d'attente d'alerte peut se lier uniquement à error, tandis qu'une file d'attente d'archivage peut se lier aux trois sévérités.
Échange Topic
C'est le type d'échange le plus flexible, permettant aux clés de liaison et aux clés de routage d'utiliser des caractères génériques. La clé de routage est traitée comme une liste délimitée (par exemple, en utilisant des points .).
*correspond exactement à un mot.#correspond à zéro ou plusieurs mots.
Une clé de routage comme orders.us.created peut aller vers une file d'attente de fraude liée à orders.*.created et une file d'attente des opérations US liée à #.us.#. Utilisez les échanges Topic lorsque vos règles de routage sont de véritables catégories métier, pas seulement un champ fixe.
Demande/Réponse : Demander une réponse spécifique
Le modèle Demande/Réponse permet à une application cliente d'envoyer un message de demande et d'attendre de manière synchrone une réponse d'un travailleur (serveur). Bien que la messagerie soit intrinsèquement asynchrone, ce modèle simule les appels de procédure distante (RPC) traditionnels sur le bus de messages.
Utiliser reply_to et correlation_id
- Le client envoie une demande à une file d'attente telle que
rpc_queue. - Le client définit
reply_tosur une file d'attente de rappel qu'il consomme. - Le client définit un
correlation_idunique. - Le travailleur traite la demande et publie la réponse dans la file d'attente
reply_to. - Le client fait correspondre la réponse à la demande d'origine en vérifiant le
correlation_id.
Cas d'utilisation
- Recherches de service : Récupérer un profil utilisateur ou un indicateur de fonctionnalité depuis un autre service.
- Décisions courtes : Vérifier le stock avant d'accepter une commande.
Utilisez-le avec précaution
Demande/Réponse est utile, mais il réintroduit l'attente synchrone dans votre système de messagerie. Définissez des délais d'attente côté client, gérez les réponses en double et évitez d'utiliser RPC pour des tâches de longue durée. Pour un travail lent, publiez une commande, renvoyez un ID de tâche et envoyez des événements de progression ou d'achèvement séparément.
Flux RPC conceptuel
graph TD
A[Client (Demandeur)] -->|1. Message de demande (incl. reply_to, correlation_id)| B(File d'attente de demande RPC);
B --> C[Serveur (Travailleur)];
C -->|2. Traiter la demande|
D[Résultat];
D -->|3. Message de réponse (via reply_to, en conservant correlation_id)| A;
Modèles RabbitMQ courants en un coup d'œil
| Modèle | Type d'échange | Mécanisme de routage | Caractéristique clé | Cas d'utilisation principal |
|---|---|---|---|---|
| Files d'attente de travail | Par défaut ou Direct | Une file d'attente partagée par les travailleurs | Un message, un consommateur | Équilibrage de charge des tâches de longue durée |
| Publier/S'abonner | Fanout | Ignore la clé de routage | Un message, toutes les files liées | Diffusions système, journalisation |
| Routage Direct | Direct | Correspondance exacte de la clé de routage | Ciblage sélectif des consommateurs | Routage basé sur la sévérité ou le type |
| Routage Topic | Topic | Correspondance par caractères génériques (*, #) |
Routage flexible et complexe | Communication entre microservices, flux d'événements |
| Demande/Réponse (RPC) | Direct (pour la réponse) | Utilise reply_to & correlation_id |
Simule des appels API synchrones | Recherches de service immédiates, petites transactions |
À retenir
Commencez par la forme de la communication. Utilisez les files d'attente de travail lorsqu'exactement un travailleur doit gérer une tâche, Pub/Sub lorsque chaque abonné doit voir un événement, le routage Direct ou Topic lorsque seuls certains abonnés doivent le voir, et Demande/Réponse uniquement lorsque l'appelant a vraiment besoin d'une réponse immédiate.