Introduction à RabbitMQ – AMQP Partie I
RabbitMQ est un broker de messages se basant sur le standard AMQP afin d’échanger avec différents clients.
Cette suite d’article présente AMQP, RabbitMQ ainsi que l’API de Spring pour établir des connections vers un broker AMQP.
AMQP
Le protocole AMQP sur lequel est basé RabbitMQ a pour but d’offrir un système d’échange totalement interopérable entre les différents acteurs. Contrairement à JMS, AMQP n’est pas une API, et de fait ne consiste pas une librairie pour une plateforme en particulier, mais est un protocole d’échange tel que HTTP ou SMTP.
AMQP tire son origine du besoin de normer un système d’échanges de messages totalement asynchrone qui de plus s’abstrait totalement de l’implémentation du broker ou du client. En d’autres termes, il est tout à fait possible d’utiliser un broker AMQP en Erlang, sur lequel un client java va envoyer des messages qui seront consommés par un second client en .Net :
Etablir la connection
AMQP table sur certains concepts pour gérer toute la communication entre les clients et le broker:
Un client va établir une connection (connection) vers le broker.
Au travers de cette connection, il pourra ouvrir un ou plusieurs channels (canaux) de communication grâce auxquels les requêtes pourront être transmises au broker, en parallèle.
Généralement, une application ne nécessite que l’ouverture d’une unique connexion; toute les communications sont ensuite effectuées au travers de plusieurs channels différents pendant la durée de vie de l’application.
Les bases d’un échange
Une fois connecté, un client va pouvoir accéder aux exchanges (échanges) et aux queues (files) pour transmettre et recevoir les messages.
L’exchange est le point où un message peut être déposé ; de là, le message suivra ensuite un cheminement pour enfin être placé dans la ou les queues de destination, où il sera entreposé jusqu’à consommation. Plusieurs client différents pourront envoyer des messages sur un même exchange, ainsi plusieurs messages envoyés pourront suivre le même mapping.
Le chemin pris par le message sera défini grâce aux bindings (liaisons) que l’on pourra appliquer entre un exchange et une queue. Ainsi il sera possible de définir la destination d’un message directement depuis le broker.
Ce système permet d’avoir un client producteur de messages indépendant du consommateur ; ainsi, en cas de changement d’architecture, il suffira de modifier les bindings adéquats sur le broker, les deux clients (producteur et consommateur) ne nécessitent alors pas de modification dans le code.
La queue est le point de consomation des messages; tout comme pour les exchanges, il est possible d’avoir plusieurs consommateurs sur une même queue.
Chaque consommateur peut demander au broker de lui envoyer le prochain message stocké dans la queue. Dès lors le message est envoyé au client et supprimé de la queue. Un message consommé n’est plus disponible, et de fait ne peut pas être consommé à nouveau.
Afin de simplifier les schémas, un client producteur de message sera symbolisé par ; un client consommateur de messages sera signalé par
; un exchange par
et une queue grâce à
Premiers échanges (mode Fanout)
Le cas le plus basique est l’envoi d’un message sur un exchange désservant une queue particulière, et la consommation sur cette queue par un unique client.
Il est aussi possible d’envoyer le même message sur deux queues différentes afin que deux consommateurs puissent le recevoir et le traiter. A ce moment là le message est dupliqué, et chaque queue contient sa propre copie.
Une autre variante consiste à déclarer plusieurs exchanges qui envoient des messages sur une queue commune.
Ici les messages reçus sur Exchange1 ou Exchange2 seront tous disponibles sur Queue2
Ce type d’échange est appelé fanout et représente une communication 1:N. Pour un exchange donné, les N queues liées pourront recevoir le message.
Utilisation des routing keys (mode Direct)
Afin de personnaliser les directions prises par un message, un système de binding/routing key est disponible. Chaque binding pourra définir sa propre binding key qui sera une chaîne de caractère identifiant un mapping précis. Les messages pourront de leur côté définir une routing key qui servira à définir au travers de quel binding le message devra passer. Une routing key est simplement un identifiant écrit sous la forme de noms séparés par des points. Par exemple si l’on devait représenter une key pour l’indice VMW, elle pourrait être sous la forme stock.us.vmw.
La routing key sera comparée aux binding keys de chaque binding disponible; si l’un correspond alors le message sera transféré uniquement sur la queue représentée dans ce binding.
Dans le cas ou la routing key ne correspondrait à aucune des possibilités, alors le message serait simplement ignoré.
Un message ayant la Routing key stock.us.vmw serait disponible sur Queue1 uniquement.
Comme auparavant il est possible d’ajouter d’autres acteurs pour augmenter les possibilités de la structure.
Les échanges de ce type sont appelés direct, ils permettent de mettre en place une communication 1:1. Pour un exchange donné, uniquement la queue dont le binding correspond à la routing key du message pourra recevoir le message.
Les wildcards (mode Topic)
Ce même système de routing/binding key est poussé au point de permettre d’utiliser des wildcards dans les noms des clefs.
Le premier type de wildcard, l’astérisque, permet de représenter un seul et unique élément dans la routing-key.
Par exemple une binding key stock.us.* pourrait représenter toutes les routing-key commençant par stock.us. et se terminant par un unique élément. Par exemple stock.us.vmw et stock.us.orcl seraient valides, stock.us.orcl.java ne le serait pas.
Un second caractère de wildcard, le dièse, est utilisable pour représenter une suite de plusieurs éléments.
Par exemple la binding key stock.# peut représenter stock.us.vmw, stock.us.orcl.java ou stock.fr.ead.
Dans cette configuration un message dont la routing key serait stock.us.orcl.java serait disponible dans Queue1 et Queue2.
Un message dont la routing key serait stock.fr.ead ne serait disponible que dans la Queue2.
Si le message avait une routing key non représentée dans les bindings, tel que fr.cac.ead, alors le message serait ignoré et ne figurerait dans aucune queue.
Les différents wildcards peuvent figurer n’importe ou dans la binding key; stock.#.orcl est donc elle aussi valide.
Ce système d’exchange est appelé le mode topic, il permet de mettre en place un échange en 1:N basé sur des règles définies dans les binding keys.
Conclusion
AMQP est un système très souple qui en plus de sa capacité à être utilisé dans n’importe quel environnement, gère la communication avec simplicité grâce aux différents systèmes d’échanges applicables.
Dans un prochain post, nous pourrons voir plus de détails le fonctionnement de AMQP: Comment définir le système d’échange utilisé, quelles sont les options disponibles pour les exchanges et queues, qui crée tous ces composants, etc.
Avec la partie II de l’article, cela fait un superbe article d’introduction à RabbitMQ!
En attendant des articles additionnels: bravo!
Sur les wildcards:
“Dans cette configuration un message dont la routing key serait stock.us.orcl.java serait disponible dans Queue1 et Queue2”. Dans Queue2 (stock.# ) et non dans Queue1 (stock.us.*)
Sinon bravo
Merci pour l’article, je me dirige vers le second niveau.
Ce qui manque pour des versions futures c’est peut être une approche fonctionnelle : des exemples d’utilisations types et aussi quand il ne faut pas l’utiliser. Enfin très bonnes bases en tout cas.
Merci bc pour cet article, une bonne introduction de rabbitmq