Académique Documents
Professionnel Documents
Culture Documents
Rabbit MQ
Rabbit MQ
RabbitMQ est un message broker très complet et robuste, c’est pourquoi le comprendre et
l’utiliser est assez simple. en revanche, le maîtriser l’est un peu moins… C’est pourquoi je
vous propose cette série de deux articles.
Bref, pour commencer, avant de manger du pâté de lapin il va falloir bouffer des carottes !
Introduction
RabbitMQ a de nombreux points forts, ce qui en fait une solution utilisable sur tous
types/tailles de projet.
En voici quelques-uns :
AMQP
Ok, donc on va commencer par semer des carottes
Le Broker
RabbitMQ est un message broker, son rôle est de transporter et router les messages depuis les
publishers vers les consumers. Le broker utilise les exchanges et bindings pour savoir si il
doit délivrer, ou non, le message dans la queue.
Le message
Le message est comme une requête HTTP, il contient des attributs ainsi qu’un payload.
Parmi les attributs du protocol vous pouvez y ajouter des headers depuis votre publisher.
L’attribut routing_key, bien qu’optionnel, n’en est pas moins très utile dans le protocol.
Les Bindings
Les bindings, ce sont les règles que les exchanges utilisent pour déterminer à quelle queue il
faut délivrer le message. Les différentes configurations peuvent utiliser la routing key
(direct/topic exchanges) ainsi que les headers(header exchanges). Dans le cas des exchanges
fanout, les queues n’ont qu’à être bindées pour recevoir le message.
Les Exchanges
Un exchange est un routeur de message. Il existe différents types de routages définis par le
type d’exchange.
Important à savoir : l’exchange amq.default est l’exchange par défaut de rabbit. Vous ne
pouvez ni le supprimer ni vous binder dessus.
Cet exchange est auto bindé avec toutes les queues avec une routing key égale au nom de
la queue.
L’exchange fanout est le plus simple. En effet il délivre le message à toutes les queues
bindées.
binding.routing_key == message.routing_key
Une routing key est composé de plusieurs segments séparés par des .. Il y a également 2
caractères utilisés dans le matching.
• foo.*.baz match
• foo.*.* match
• foo.# match
• foo.#.baz match
• *.*.baz match
• #.baz match
• #.bar.baz match
• # match
• foo.* non trouvé
match(binding.routing_key, message.routing_key)
L’exchange headers délivre le message si les headers du binding matchent les headers du
message.
L’option x-match dans le binding permet de définir si un seul header ou tous doivent
matcher.
x-match = any
Avec le x-match = any le message sera délivré si un seul des headers du binding correspond
à un header du message.
OU
x-match = all
Avec le x-match = all le message sera délivré si tous les headers du binding correspondent
aux headers du message.
Ici le message sera délivré seulement si les headers attrName1 ET attrName2 (du binding)
sont égaux aux headers attrName1 et attrName2 du message.
Les Queues
Une queue est l’endroit où sont stockés les messages. Il existe des options de configuration
afin de modifier leurs comportements.
Quelques options :
Vous publiez dans un exchange. Vous ne consommez pas un exchange ! (quand vous croyez
publier dans une queue en réalité le message est publié dans l’exchange amq.default avec la
routing key = queue name)
Consumer
Le rôle du consumer est d’exécuter un traitement après avoir récupéré un ou plusieurs
messages.
Vous pouvez maintenant consulter la partie 2 (maîtrise), dans laquelle nous verrons comment
attraper les lapins, et comment préparer le pâté.
Liens utiles
http://www.rabbitmq.com/documentation.html
Introduction
Après avoir vu les bases dans RabbitMQ : Les bases (Partie 1), nous allons pousser un peu
plus loin l’utilisation de RabbitMQ.
Plugins
Les plugins sont comme des engrais pour votre champ de carottes.
Je vous invite à consulter la page des plugins ainsi que le Github afin de voir les plugins
officiels disponibles.
D’autre part je vous conseille fortement d’activer au minimum les plugins suivants :
Authentification / Autorisation
Dans tout système d’informations, l’utilisation de permissions, par utilisateur/groupe, est une
notion très importante. Elle permet d’organiser et maîtriser l’utilisation et l’accès au service.
ℹ️ Avec le plugin rabbitmq-auth-backend-http vous pouvez même déléguer cette partie à une
API HTTP (Les utilisateurs de votre plateforme sont connectés à RabbitMQ ! ). Voici une
implémentation en PHP qui utilise le composant security de Symfony.
auth_backends.my_auth_1 = internal
auth_backends.my_auth_2 = http
...
Ici les valeurs my_auth_1 et my_auth_2 sont arbitraires et peuvent prendre n’importe quelle
valeur.
Utilisateur
Un utilisateur (username, password facultatif) est utilisé pour se connecter à RabbitMQ afin
de publier et consommer les messages.
Une fois votre utilisateur créé, il faudra lui ajouter des permissions sur chaque vhost auxquels
il aura accès.
• Configure regexp
• Write regexp
• Read regexp
Pour une utilisation plus simple des regexp je vous conseille d’avoir une vraie stratégie de
nommage des exchanges/queues avec des préfixes/segments/suffixes. D’une part vous
pourrez plus facilement identifier qui a créé les ressources mais aussi qui les consomme.
Policies
Les policies sont des règles de configurations qui s’appliquent aux exchanges et aux queues
(dont le nom matche une regexp) afin de diminuer la redondance de configuration mais aussi
et surtout de pouvoir changer une policy sans avoir à détruire et recréer la ressource
(exchange/queue). Certaines options de configuration d’une policy sont spécifiques aux
exchanges et d’autres aux queues.
• federation plugin
• mirrored queues
• alternate exchanges
• dead lettering
• per-queue TTLs
• maximum queue length.
ℹ️ Avec cette solution on peut facilement gérer des “délais avant retry” variables. Premier retry
à 5 secondes, deuxième à 10 secondes, etc… Je garde une réserve sur cette pratique car
elle fonctionne mais positionne la responsabilité du retry du côté applicatif.
• NACK le message avec un délai avant de retry le message (Le “délai avant retry” est
fixe -> retry retardé fix non bloquant)
Le message va être remis en début de queue après avoir été mis en attente pendant un
temps défini.
Pour mettre en place cette solution nous allons devoir créer un exchange et une queue
d’attente.
Créer un exchange qui va router les messages dans la queue d’attente waiting_5 type
fanout. Créer une queue d’attente waiting_5 avec x-dead-letter-exchange: "" et x-
message-ttl: 5000. Puis binder cette queue sur l’exchange waiting_5.
ℹ️ À noter que le retry est infini. Ce qui peu également créer des poison messages.
Poison message
Un poison message c’est un message que le consumer rejettera (NACK) à chaque fois qu’il
va le consommer. Afin de traiter les poisons messages il faut que le consumer regarde dans les
properties du message afin de vérifier que le nombre de tentatives n’a pas été atteint.
Si le nombre de retry a été atteint il faudra loguer une erreur et ACK le message.
Production
Consultez la documentation sur les recommandations pour les serveurs de production.
Liens utiles
https://www.rabbitmq.com/admin-guide.html