Blog Zenika

#CodeTheWorld

Java

Introduction à RabbitMQ – RabbitMQ, le vif du sujet

Après avoir vu le fonctionnement d’AMQP concernant la gestion des échanges entre les différents acteurs, nous allons pouvoir entrer dans le sujet même avec une implémentation de ce protocole. SpringSource propose la sienne, RabbitMQ.

RabbitMQ

rabbitmq_logo_strap.png
En tant qu’implémentation d’AMQP, RabbitMQ répond aux règles citées dans les billets précédents, mais il apporte aussi quelques particularités non précisées dans les spécifications.
Entre autres, il sera facile de mettre en place une solution de cluster pour une meilleure tolérance de panne et une meilleure tenue de charge. Il sera aussi aisé de gérer de la sécurité au sein des utilisateurs autorisés à se connecter pour permettre la configuration ou les accès à certains éléments.
RabbitMQ a aussi une capacité d’extensibilité via une panoplie de plugins ajoutant de nouvelles fonctionnalités au broker de base.
Par défaut une instance de RabbitMQ fournit un VHost appelé ‘/‘, ce qui permet sans configuration supplémentaire de lancer le broker et de l’utiliser tel quel.
De même, un utilisateur nommé ‘guest‘ dont le mot de passe est ‘guest‘ sera accessible. Attention cependant, celui-ci possède les droits d’administration par défaut.

Erlang

erlang-logo.png RabbitMQ est écrit en Erlang, langage développé par Ericsson (la société connue pour tout ce qui est mobile et télécommunication) avec pour but principal le support d’applications distribuées, et la tolérance de panne.
Le petit plus qui a poussé l’équipe de développement de RabbitMQ à choisir Erlang, est l’aisance avec laquelle on peut gérer un protocole réseau programmatiquement.
Tout est donc fait pour avoir un système à la fois fiable et robuste.
Afin de lancer des applications codées en Erlang, il est nécéssaire d’installer un environnement spécifique. Heureusement, Erlang est prévu pour être multi-plateformes, il est donc disponible sur la plupart des OS courants.
Les utilisateurs de Windows pourront trouver un installeur sur le site officiel d’Erlang, quant aux linuxiens, il leur suffira de l’installer via le gestionnaire de paquets de leur distribution.
Les utilisateurs de Mac OS devront par contre passer par une procédure plus complexe. Le plus simple est d’utiliser MacPort, un gestionnaire de paquets similaire à ceux disponible sous linux (APT en particulier). Il est aussi possible de compiler soi-même l’environnement, celui-ci étant open-source.
L’aspect multiplateformes d’Erlang, et donc de RabbitMQ, permet donc de lancer un cluster sur un environnement hétérogène. Voyons comment.

Lancer RabbitMQ

Installation

Maintenant qu’Erlang est installé, il ne reste plus qu’à télécharger la dernière version de RabbitMQ, soit grâce à votre gestionnaire de paquets, soit via le site officiel.
Pour commencer avec RabbitMQ, il suffira d’extraire l’archive dans un répertoire quelconque, puis de lancer l’exécutable ‘sbin/rabbitmq-server‘ (ou ‘sbin/rabbitmq-server.bat‘ sous Windows) depuis un terminal.
Avant de détailler plus avant les options de RabbitMQ, voici un petit listing des différents exécutables disponibles dans le dossier /sbin :

  • rabbitmq-server; Exécutable qui permet de démarrer une simple instance de RabbitMQ (appellée aussi un noeud). L’option ‘-detached‘ va permettre de lancer l’application en arrière-plan en tant que démon.
  • rabbitmq-multi; Tout comme rabbitmq-server, cet exécutable permet de démarrer un noeud RabbitMQ. Cet exécutable lance plusieurs noeuds sur une seule et même machine, ce qui peut s’avérer utile pour tester sa mise en cluster.
  • rabbitmqctl; L’outil d’administration d’un noeud RabbitMQ. Grace à l’option ‘-n node_name‘ il sera possible de choisir sur quel noeud précisément l’on souhaite travailler (en particulier lorsque l’on travaille avec plusieurs noeuds sur une même machine). C’est cet outil qui entre autres va permettre de mettre en place un cluster.

En résumé, pour lancer une instance de RabbitMQ il suffit d’éxécuter :

./rabbitmq-server start -detached

Gestion d’un nouvel utilisateur (et de ses droits)

A partir d’ici il est possible de se connecter depuis l’extérieur sur le broker et d’échanger les premiers messages. Encore une fois attention, par défaut le seul utilisateur disponible ‘guest‘ est administrateur. Pour des raisons de sécurité évidentes, si l’on travaille sur un système en production, il sera nécéssaire de créer un nouvel utilisateur et de supprimer les droits d’administration de guest.

./rabbitmqctl add_user colin P@sSw0rd
./rabbitmqctl set_admin colin
./rabbitmqctl clear_admin guest

Ceci étant fait, le nouvel utilisateur n’a pour l’instant aucun droit sur les composants existants sur le broker. En effet, même s’il possède les droits d’administration généraux, il faut lui accorder précisément les droits sur un VHost en particulier.
Le VHost présent par défaut est pour rappel ‘/‘.
Le système de droits fonctionne de la manière suivante : trois expressions régulières, correspond au nom des élément (queue, exchange) à administrer, sont définies sur un VHost. Elles permettent de définir les droits de configuration, écriture et lecture.
L’écriture est la possibilité d’écrire sur les exchanges spécifiés et la lecture est la possibilité de lire sur les queues données.
Pour donner les droits complets au nouvel utilisateur la commande à utiliser sera :

./rabbitmqctl set_permissions colin .* .* .*

Mise en place d’un cluster

RabbitMQ_Cluster.png
Maintenant un broker AMQP est lancé et est disponible. Un coup d’oeil sur le statut actuel du noeud nous permet de récupérer quelques informations qui seront importantes par la suite :

Mac-Colin:sbin Colin$ ./rabbitmqctl status
Status of node 'rabbit@Mac-Colin' ...
[{running_applications,[{rabbit,"RabbitMQ","2.2.0"},
                        {os_mon,"CPO  CXC 138 46","2.2.5"},
                        {sasl,"SASL  CXC 138 11","2.1.9.2"},
                        {mnesia,"MNESIA  CXC 138 12","4.4.15"},
                        {stdlib,"ERTS  CXC 138 10","1.17.1"},
                        {kernel,"ERTS  CXC 138 10","2.14.1"}]},
 {nodes,[{disc,['rabbit@Mac-Colin']}]},
 {running_nodes,['rabbit@Mac-Colin']}]
...done.

Première chose, le noeud ici se nomme ‘rabbit@Mac-Colin‘, par défaut un noeud aura pour nom ‘rabbit@hostname‘.
La première partie donne les informations sur les applications (et plugins) actuellement rattachés au noeud, entre autres il est possible de voir la version actuelle de RabbitMQ (ici 2.2.0).
La seconde partie plus importante dans le contexte de cluster va donner les informations sur les différents noeuds déclarés dans le système et ceux actuellement disponibles.

Modes d’un noeud

Pour l’instant dans le listing des nodes, il n’y a que ‘rabbit@Mac-Colin‘ qui est actuellement en mode disk. Les noeuds pourront être créés sous deux modes différents, RAM et disk.
Un noeud en mode RAM ne stockera les informations que de façon volatile dans la RAM, hormis évidemment les éléments classés comme persistants (durable).
Un noeud en mode disk travaillera aussi avec la RAM, mais pourra se baser sur le disque pour conserver les données.
L’avantage du mode RAM est qu’il est plus rapide puisque tout est conservé en mémoire, seulement il est possible de perdre des données en cas de problème, le mode disk lui protège ses données en les enregistrant régulièrement.
Il est conseillé d’avoir au moins un noeud en mode disk sur tout le cluster, cependant il est tout à fait possible de travailler sans aucun node en mode disk.

Lancement de nouvelles instances

Pour avoir un cluster fonctionnel, il va falloir démarrer de nouveaux noeuds.
Le choix le plus classique est de démarrer RabbitMQ sur une nouvelle machine, mais il est aussi possible de lancer plusieurs instances sur une seule et unique machine.

Multiple machines

Afin de communiquer en toute sécurité, les différents noeuds vont utiliser un cookie fourni par erlang. Tous les noeuds ayant le même cookie pourront échanger sans problème. Pour ça il suffit de récupérer un de ces cookies sur une des machines ayant lancé RabbitMQ. La documentation spécifie que ce cookie est disponible dans ‘/var/lib/rabbitmq/.erlang.cookie‘ sous Unix ou ‘C:Documents and SettingsCurrent UserApplication DataRabbitMQ.erlang.cookie‘ sous Windows, seulement durant mes tests je n’ai trouvé ce fichier cookie que dans mon dossier personnel.

Mac-Colin:sbin Colin$ cat ~/.erlang.cookie
ILJHQPNLJPLBZFCJNBIZ

Avec ce cookie, il est possible de démarrer les autres instances de manière à ce qu’elles puissent communiquer avec le noeud d’origine. La méthode la plus simple pour démarrer les autres noeuds est de passer le cookie par l’option ‘-setcookie cookie‘.

Linux-Colin:sbin Colin$ ./rabbitmq-server start -detached -setcookie ILJHQPNLJPLBZFCJNBIZ
BSD-Colin:sbin Colin$ ./rabbitmq-server start -detached -setcookie ILJHQPNLJPLBZFCJNBIZ

Une autre manière de faire serait simplement de créer/remplacer le fichier ‘.erlang.cookie‘ sur les autres machines avec comme contenu la chaîne de caractères.
Les noms des noeuds ici seront respectivement ‘rabbit@Linux-Colin‘ et ‘rabbit@BSD-Colin‘.

Mode multi

S’il n’est pas possible de lancer lancer un autre noeud sur une nouvelle machine, l’exécutable ‘rabbitmq-multi‘ va permettre de lancer plusieurs instances sur une seule et unique machine physique. Tout d’abord il faudra arrêter l’instance actuelle, puis démarrer autant de noeuds que nécéssaire.
Les noeuds étant tous sur la même machine, et partageant le même fichier de cookie, il ne sera pas nécéssaire d’effectuer l’étape vue au dessus.

Mac-Colin:sbin Colin$ ./rabbitmq-server stop
Mac-Colin:sbin Colin$ ./rabbitmq-multi start_all 3 #Ici trois noeuds sont créés en local

Dans les messages affichés à l’écran il devrait y avoir les noms des trois nodes créés, dans mon cas ‘rabbit@Mac-Colin‘, ‘rabbit_1@Mac-Colin‘ et ‘rabbit_2@Mac-Colin‘. Pour administrer les noeuds via rabbitmqctl il faudra spécifier l’option ‘-n node_name‘ pour que les modifications soient appliqués sur un noeud en particulier, sinon c’est le noeud ‘rabbit@Mac-Colin‘ qui subira les changements.

Ajout des différents noeud au même cluster

Pour ajouter les noeuds, il n’est pas nécéssaire de couper le système, seul les nouveaux arrivants devront être purgés avant de joindre le cluster.
L’instance principale ici sera ‘rabbit@Mac-Colin‘.

Noeud en mode RAM

La première étape sera d’ajouter le noeud Linux au cluster en mode RAM

Linux-Colin:sbin Colin$ ./rabbitmqctl stop_app #Arrête l'instance de RabbitMQ sans quitter l'application
Stopping node 'rabbit@Linux-Colin' ...
...done.
Linux-Colin:sbin Colin$ ./rabbitmqctl reset #Vide les données qui pourraient-être présente en base/mémoire
Resetting node 'rabbit@Linux-Colin' ...
...done.
Linux-Colin:sbin Colin$ ./rabbitmqctl cluster rabbit@Mac-Colin #Rejoint le cluster en mode RAM
Clustering node 'rabbit@Linux-Colin' with ['rabbit@Mac-Colin'] ...
...done.
Linux-Colin:sbin Colin$ ./rabbitmqctl start_app #Relance l'instance de RabbitMQ qui cette fois-ci est liée au cluster
....

Et le résultat est visible depuis le premier noeud :

Mac-Colin:sbin Colin$ ./rabbitmqctl status
Status of node 'rabbit@Mac-Colin' ...
[{running_applications,[...]},
 {nodes,[{disc,['rabbit@Mac-Colin']},{ram,['rabbit@Linux-Colin']}]},
 {running_nodes,['rabbit@Linux-Colin','rabbit@Mac-Colin']}]
...done.

Noeud en mode disk

Maintenant pour ajouter le noeud BSD en mode disk, la seule variante sera sur la commande cluster, qui nécessite de spécifier le nom du nouveau noeud dans la commande.

BSD-Colin:sbin Colin$ ./rabbitmqctl stop_app
Stopping node 'rabbit@BSD-Colin' ...
...done.
BSD-Colin:sbin Colin$ ./rabbitmqctl reset
Resetting node 'rabbit@BSD-Colin' ...
...done.
BSD-Colin:sbin Colin$ ./rabbitmqctl cluster rabbit@Mac-Colin rabbit@BSD-Colin #Rejoint le cluster en mode disk
Clustering node 'rabbit@BSD-Colin' with ['rabbit@Mac-Colin', 'rabbit@BSD-Colin'] ...
...done.
BSD-Colin:sbin Colin$ ./rabbitmqctl start_app
...

Encore une fois le résultat sera visible depuis n’importe quel noeud :

Mac-Colin:sbin Colin$ ./rabbitmqctl status
Status of node 'rabbit@Mac-Colin' ...
[{running_applications,[...]},
 {nodes,[{disc,['rabbit@BSD-Colin','rabbit@Mac-Colin']}, {ram,['rabbit@Linux-Colin']}]},
 {running_nodes,['rabbit@BSD-Colin','rabbit@Linux-Colin', 'rabbit@Mac-Colin']}]
...done.

Il faudra bien évidemment penser à l’option ‘-n nodename‘ si l’on est en mode rabbitmq-multi, et si l’on travaille via du réseau, les différentes machines devront pouvoir intéragir entre elles uniquement via leur hostname.

Bonus

Petit bonus offert par RabbitMQ concernant le fonctionnement de base de AMQP, jusqu’à présent il a été dit qu’un binding ne se faisait que entre un exchange et une queue. RabbitMQ permet d’établir un binding entre deux exchanges différents. Ainsi il est très simple d’ajouter de nouvelles fonctionnalités en parallèle, pour faire du log par exemple, sans avoir à modifier le mapping déjà existant. ExchangeToExchange.png
Le fonctionnement est très simple et se base sur les bindings que l’on pourrait avoir entre un exchange et une queue, donc rien de bien neuf et pourtant une fonctionnalité très pratique si l’on veut faire des ajouts sur une structure existante sans l’abîmer.

Conclusion

Voilà tout pour ce qui est de l’installation et l’administration de base d’un noeud RabbitMQ. Il reste encore beaucoup de choses à voir, comme Spring-AMQP qui permettra de développer des applications Java qui interagiront avec un broker AMQP, ou encore les différents plugins et possibilités offertes par RabbitMQ.
Rob Harrop qu’on ne présente plus, sera d’ailleurs à la What’s Next Paris et présentera RabbitMQ dans un contexte d’interopérabilité. Je vous invite à lire l’abstract qui est disponible dans l’agenda. En espérant vous y voir!

Auteur/Autrice

2 réflexions sur “Introduction à RabbitMQ – RabbitMQ, le vif du sujet

  • Vraiment une excellente série !

    Cependant concernant la commande:
    $rabbitmqctl set_permissions user .* .* .*

    RabbitMQ v2.4.1 me retourne une erreur. Cependant cette commande semble être valide:
    $rabbitmqctl set_permissions user / . .

    Je suis encore en plein découverte de RabbitMQ (aucun client & producer de connecté pour le moment) mais pouvez-vous confirmer ou non si cette commande est valide ?

    Merci.

    Répondre
  • Bonjour,
    interessant mais connaissez-vous un site web ou catalogue de plugin RabbitMQ (je suis en recherche d’un plugin de contrôle des accès aux zones d’échanges et queues RabbitMQ par un serveur CAS sous SSO) ?

    Merci

    Répondre

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.