<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Erlang on Zwindler's Reflection</title><link>https://blog.zwindler.fr/tags/erlang/</link><description>Recent content in Erlang on Zwindler's Reflection</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>Licensed under CC BY-SA 4.0</copyright><lastBuildDate>Tue, 16 Apr 2019 11:45:07 +0000</lastBuildDate><atom:link href="https://blog.zwindler.fr/tags/erlang/index.xml" rel="self" type="application/rss+xml"/><item><title>Suivez le lapin Orange – Intro et bonnes pratiques d’infra RabbitMQ</title><link>https://blog.zwindler.fr/2019/04/16/suivez-le-lapin-orange-intro-et-bonnes-pratiques-dinfra-rabbitmq/</link><pubDate>Tue, 16 Apr 2019 11:45:07 +0000</pubDate><guid>https://blog.zwindler.fr/2019/04/16/suivez-le-lapin-orange-intro-et-bonnes-pratiques-dinfra-rabbitmq/</guid><description>&lt;img src="https://blog.zwindler.fr/2019/04/rabbitmq_logo2.webp" alt="Featured image of post Suivez le lapin Orange – Intro et bonnes pratiques d’infra RabbitMQ" /&gt;&lt;h2 id="cest-quoi-rabbitmq-"&gt;C’est quoi RabbitMQ ?
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://www.rabbitmq.com/" target="_blank" rel="noopener"
&gt;RabbitMQ&lt;/a&gt;® est un logiciel open source, développé par Pivotal. Il s’agit d’un message broker (bus/agent de messages), très simple à mettre en place, multiplateforme et multiprotocole (AMQP, MQTT, STOMP).&lt;/p&gt;
&lt;p&gt;RabbitMQ est donc particulièrement adapté pour monter rapidement une architecture microservice, &lt;strong&gt;voire même IoT&lt;/strong&gt;, nécessitant un bus de message pour garantir les communications entre les différentes briques de cette architecture.&lt;/p&gt;
&lt;p&gt;C’est justement dans mon contexte pro : nous disposons d’une architecture logicielle aux composantes très différentes (microservices, machines outils connectées, &amp;hellip;). Nous avons donc besoin de cette agilité, qu’on ne retrouve pas forcément dans les autres messages brokers, mais aussi de garanties et des contrôles sur les transports des messages que nous n’aurions pas forcément avec des API REST.&lt;/p&gt;
&lt;h2 id="architecture-et-bonnes-pratiques"&gt;Architecture et bonnes pratiques
&lt;/h2&gt;&lt;p&gt;Voici à quoi ressemble l’architecture RabbitMQ que nous utilisons :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/04/RabbitMQ_archi.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;A première vue, c’est assez simple. Mais si vous vous demandez si nous n’aurions pas pu faire encore plus simple, alors cet article est fait pour vous ;).&lt;/p&gt;
&lt;h2 id="amqps--webmqtts"&gt;AMQP&lt;u&gt;S&lt;/u&gt; / WebMQTT&lt;u&gt;S&lt;/u&gt;
&lt;/h2&gt;&lt;p&gt;Les plus observateurs d’entre vous auront peut être remarqués le « S » à la fin des deux protocoles que nous utilisons pour faire communiquer nos services entre eux :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AMQP / AMQPS&lt;/li&gt;
&lt;li&gt;WebMQTT / WebMQTTS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vous l’aurez sûrement deviné, il s’agit de la déclinaison non-sécurisée/sécurisée (chiffrée) de chacun de ces protocoles.&lt;/p&gt;
&lt;p&gt;Par défaut dans RabbitMQ, les échanges ne sont pas chiffrés. Bien qu’il n’y ait pas de réponse universelle à la question « dois-je chiffrer l’ensemble de mes flux ? », l’Ops que je suis ne peux pas s&amp;rsquo;empêcher de répondre un grand &lt;strong&gt;OUI&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;C’est particulièrement vrai dans notre cas, où une partie des flux transite par Internet, et l’autre transite à l’intérieur du réseau de notre cloud provider. L’ajout du chiffrement est &lt;em&gt;obligatoire&lt;/em&gt;. Le risque d’espionnage, de détournement d’information, de Man in the Middle, sont suffisamment sérieux pour qu’on prenne le temps de configurer un chiffrement TLS.&lt;br&gt;
Cependant, l’impact sur les performances globales de la plateforme est réel et devra être pris en compte lors du choix de l’architecture.&lt;/p&gt;
&lt;h2 id="comment-activer-le-chiffrement-tls-sur-mes-interfaces-rabbitmq-"&gt;Comment activer le chiffrement TLS sur mes interfaces RabbitMQ ?
&lt;/h2&gt;&lt;p&gt;Tout se passe dans les fichiers de configuration. Il faudra déposer les fichiers de certificats (CA, certificat public et clé privée) et rajouter les lignes suivantes dans votre configuration :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;[
{rabbit, [{ssl_options, [{cacertfile, /path/to/testca/cacert.pem&amp;#34;},
{certfile, /path/to/server_certificate.pem&amp;#34;},
{keyfile, /path/to/server_key.pem&amp;#34;},
{verify, verify_peer},
{fail_if_no_peer_cert, true}]}]}
].
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Cependant, là aussi par défaut, il n’y a pas de restrictions sur les protocoles disponibles. Or, les failles sur SSL et TLS 1.0 de ces dernières années nous obligent à désactiver ces protocoles obsolètes (voire même TLS 1.1 aussi), ainsi que tous les ciphers non sécurisés, ce qui va nettement complexifier notre configuration :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;%% -*- mode: erlang -*-
[
{ssl, [
{versions, [&amp;#39;tlsv1.2&amp;#39;]}
]},
{rabbit, [
{ssl_listeners, [5672]},
{ssl_options, [
{cacertfile, /etc/rabbitmq/certs/cacert.pem&amp;#34;},
{certfile, /etc/rabbitmq/certs/cert.pem&amp;#34;},
{keyfile, /etc/rabbitmq/certs/key.pem&amp;#34;},
{versions, [&amp;#39;tlsv1.2&amp;#39;]},
{ciphers, [
{ecdhe_ecdsa,aes_256_gcm,null,sha384},
{ecdhe_rsa,aes_256_gcm,null,sha384},
{ecdhe_ecdsa,aes_256_cbc,sha384,sha384},
{ecdhe_rsa,aes_256_cbc,sha384,sha384},
{ecdh_ecdsa,aes_256_gcm,null,sha384},
{ecdh_rsa,aes_256_gcm,null,sha384},
{ecdh_ecdsa,aes_256_cbc,sha384,sha384},
{ecdh_rsa,aes_256_cbc,sha384,sha384},
{dhe_rsa,aes_256_gcm,null,sha384},
{dhe_dss,aes_256_gcm,null,sha384},
{dhe_rsa,aes_256_cbc,sha256},
{dhe_dss,aes_256_cbc,sha256}
]},
{verify, verify_peer},
{fail_if_no_peer_cert, false}]}
]}
].
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A noter, depuis la version 3.7 de RabbitMQ (dernière version en date, la 3.8 sort bientôt), le format de la configuration a changé (erlang =&amp;gt; sysctl) pour être plus lisible et plus simple à automatiser. Cependant, à ma connaissance, il n’est pas possible de configurer l’ensemble des limitations de ciphers/protocoles.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;« While the new config format is more convenient for humans to edit and machines to generate, it is also relatively limited compared to the classic config format used prior to RabbitMQ 3.7.0. »&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="et-pourquoi-3-nœuds-et-pas-juste-un-au-milieu-"&gt;Et pourquoi 3 nœuds et pas juste un, au milieu ?
&lt;/h2&gt;&lt;p&gt;Cette question est volontairement provocatrice ;-p.&lt;/p&gt;
&lt;p&gt;Comme tout service informatique, les objectifs en terme d’indisponibilités tendent forcément vers 0. Un moyen classique d’approcher cet objectif est de redonder les composants informatiques, pour éviter tout &lt;em&gt;Single Point of Failure&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ça tombe très bien, puisque RabbitMQ propose nativement un mécanisme de clustering. Et comme dans tout cluster disposant d’un mécanisme de vote/d’élection, il est fortement conseillé d’avoir un nombre impair de nodes pour résoudre les cas de split brain (la majorité l&amp;rsquo;emporte en cas de partition réseau). D’où les 3 nœuds (mais on peut en avoir 5, 7, &amp;hellip;).&lt;/p&gt;
&lt;h2 id="le-clustering-dans-rabbitmq-comment-ça-marche-"&gt;Le clustering dans RabbitMQ, comment ça marche ?
&lt;/h2&gt;&lt;p&gt;Pour simplifier notre vie, le cluster RabbitMQ agit de telle sorte que tous les objets logiques (utilisateurs, queues, &amp;hellip;), où qu’ils soient, sont &lt;em&gt;connus&lt;/em&gt; et &lt;em&gt;adressables&lt;/em&gt; depuis tous les membres (attention, je n’ai pas dis &lt;em&gt;répliqués&lt;/em&gt;, on y reviendra).&lt;/p&gt;
&lt;p&gt;Ça, c’est super pratique. Quel que soit le nœud qu’on va contacter, si la queue est présente sur un autre serveur RabbitMQ, le message sera redistribué de manière transparente vers le nœud qui possède la queue.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2019/04/rabbitmq_cluster_redirect8229614691310308292.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Pour « masquer » la complexité induite par l’ajout de serveurs RabbitMQ supplémentaires, on a donc juste à ajouter un loadbalancer en amont du cluster. Le développeur envoie simplement le message au loadbalancer. Peu importe le nœud sur lequel le message sera réellement envoyé ensuite, il sera transféré instantanément.&lt;/p&gt;
&lt;h2 id="comment-démarrer-un-cluster-"&gt;Comment démarrer un cluster ?
&lt;/h2&gt;&lt;p&gt;Sans rentrer dans le détail de toutes les opérations nécessaires pour bootstrapper un cluster, ce qu’il faut savoir c’est que tous les nœuds doivent évidemment pouvoir se contacter et si possible être relativement &lt;em&gt;proches&lt;/em&gt; (en terme de latence).&lt;/p&gt;
&lt;p&gt;Les serveurs RabbitMQ doivent être configurés de manière à partager une même passphrase dans le fichier &lt;em&gt;/var/lib/rabbitmq/.erlang.cookie&lt;/em&gt;, et on doit ensuite joindre un des noeuds depuis les deux autres avec la commande suivante :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;#sur le node rabbit2, puis rabbit3
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@rabbit1
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;la documentation qui est très bien écrite.&lt;/p&gt;
&lt;h2 id="maintenant-on-est-hautement-disponibles-"&gt;Maintenant, on est hautement disponibles ?
&lt;/h2&gt;&lt;p&gt;Vous vous dites : « Chouette ! J’ai un cluster ! Je suis hautement disponible ! »&lt;/p&gt;
&lt;p&gt;Et bien&amp;hellip; non.&lt;/p&gt;
&lt;p&gt;Un point pouvant induire une grande confusion dans RabbitMQ est la terminologie « cluster RabbitMQ ». Le fait de monter un cluster laisse penser que tout devient automatiquement hautement disponible.&lt;/p&gt;
&lt;p&gt;Or, en réalité, comme je l’ai écris plus haut, il s’agit uniquement de rendre &lt;em&gt;accessible&lt;/em&gt; et &lt;em&gt;addressable&lt;/em&gt; l’ensemble des objets logiques depuis tous les nœuds. En revanche, les queues, et a fortiori leur contenu, ne sont physiquement présentes que &lt;em&gt;sur un nœud et un seul&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Ainsi, si un nœud du cluster disparaît, toutes les queues qu’il possède seront détruites (si elles sont Transient), ou bloquées jusqu’à ce que le nœud soit de nouveau disponible (si elles sont Durable).&lt;/p&gt;
&lt;p&gt;Dans tous les cas, il y aura interruption de service et éventuellement perte de messages, malgré le fait qu’on ait un cluster !&lt;/p&gt;
&lt;h2 id="haute-disponibilité-des-queues"&gt;Haute disponibilité des queues
&lt;/h2&gt;&lt;p&gt;Heureusement, il est également possible de répliquer les queues et leur contenu sur une partie ou la totalité des nœuds disponibles dans le cluster. On dispose alors d’une queue principale et de miroirs qui pourront prendre le relai en cas de défaillance d’un nœud.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/04/rabbitmq_master_relocate.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Ceci est configurable, par queue ou par policy (applicable à toutes les queues correspondant au pattern), avec les options &lt;em&gt;ha-mode&lt;/em&gt;, &lt;em&gt;ha-params&lt;/em&gt; et &lt;em&gt;ha-sync-mode&lt;/em&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ha-mode&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;all&lt;/strong&gt; : synchronisera votre queue sur des miroirs présents sur tous les nœuds du cluster&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;exactly&lt;/strong&gt; : permettra d’indiquer, en positionnant également un nombre sur &lt;strong&gt;ha-params&lt;/strong&gt;, le nombre exact de nœuds sur lesquels les queues sont répliquées&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;nodes&lt;/strong&gt; : synchronisera des miroirs sur une liste de nœuds explicitement nommés&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ha-sync-mode&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;automatic&lt;/strong&gt; : en cas d’apparition d’un nouveau miroir, tous les messages sont synchronisés immédiatement&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;manual&lt;/strong&gt; : en cas d’ajout d’un nouveau miroir, seul les nouveaux messages sont synchronisés&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Attention au mode &lt;strong&gt;automatic&lt;/strong&gt;, surtout en conjugaison avec le &lt;strong&gt;ha-mode&lt;/strong&gt; à &lt;strong&gt;all&lt;/strong&gt;. En effet, si ce mode est plus sécurisé puisqu’il garantie que tous les nœuds ont bien la totalité des messages, il a aussi l’inconvénient de bloquer les queues « à synchroniser » (tant que l’ensemble des messages ne sont pas répliqués partout).&lt;br&gt;
Dernier point d’attention, au même titre que le chiffrement, l’ajout de la haute disponibilité (et du clustering, dans une moindre mesure) a un impact sur les performances globales de la plateforme.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;RabbitMQ est un outil puissant et extrêmement simple à mettre en place. On peut le lancer et obtenir un broker de message robuste avec une simple commande « docker run ».&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;docker run -d --hostname my-rabbit --name some-rabbit rabbitmq:3
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pour autant, dans un environnement de production avec des objectifs en terme de haute disponibilité, il n’est pas si trivial de trouver les bons paramètres. Certains nécessiteront un peu de recherche et de configuration &lt;strong&gt;erlang&lt;/strong&gt;, d’autres nécessiteront un peu de benchmarking et de tuning, si les performances commencent à devenir un problème.&lt;/p&gt;
&lt;p&gt;Pour cette seconde catégorie, j’y reviendrai dans un autre article. Cependant, sachez quand même qu’on peut traiter sans trop de difficulté des milliers de messages par secondes, même avec des machines disposant de peu de CPU. Vous aurez surement le temps de voir venir ;).&lt;/p&gt;</description></item><item><title>Répartir les queues équitablement entre vos nœuds RabbitMQ</title><link>https://blog.zwindler.fr/2018/04/04/plugin-queue-master-balancer/</link><pubDate>Wed, 04 Apr 2018 17:00:02 +0000</pubDate><guid>https://blog.zwindler.fr/2018/04/04/plugin-queue-master-balancer/</guid><description>&lt;img src="https://blog.zwindler.fr/2018/04/rabbitmq_master_relocate.webp" alt="Featured image of post Répartir les queues équitablement entre vos nœuds RabbitMQ" /&gt;&lt;h2 id="rabbitmq-quoi"&gt;RabbitMQ quoi?
&lt;/h2&gt;&lt;p&gt;Je vais être honnête, il y a 2 mois je ne connaissais pas grand chose aux messages brokers. Et depuis j’ai découvert RabbitMQ.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Messaging that just works&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Quoi de mieux pour mettre le pied à l’étriller que ce genre de logiciel qui vous explique d’emblée que ça va être simple ? Bon en réalité ça n’a pas été si simple que ça ;-)&lt;/p&gt;
&lt;p&gt;RabbitMQ est un message broker open source écrit en erlang (er-quoi ?? oui, moi non plus&amp;hellip;). Il est développé par les équipes Pivotal, qui a repris le projet en mai 2013.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/04/rabbitmq_by_pivotal.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;C’est donc une sorte de bus central de communication pour faire transiter des messages d’applications vers applications ([1:n]-to-[1:n]) sans qu’elles se parlent en direct. C’est particulièrement pratique dans le cas de microservices dont on veut découpler et donc sécuriser les échanges (plutôt que de faire du HTTP en best effort).&lt;/p&gt;
&lt;h2 id="pourquoi-rabbitmq-"&gt;Pourquoi RabbitMQ ?
&lt;/h2&gt;&lt;p&gt;L’avantage vraiment mis en avant par RabbitMQ, c’est qu’il est simple. Mais il est aussi puissant et relativement complet.&lt;/p&gt;
&lt;p&gt;Il a l’avantage de supporter plusieurs protocoles (ce que les messages broker ne font pas tous), d’apporter une couche d’abstraction utile avec la notion d’&lt;strong&gt;exchange&lt;/strong&gt; et de permettre sans effort la création du clusters via une simple ligne de commandes. J’aurai probablement l’occasion de revenir sur les « clusters » de RabbitMQ (notez les guillemets).&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/04/hello-world-example-routing.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Source : Tutoriel helloworld de RabbitMQ // &lt;a class="link" href="https://www.rabbitmq.com/tutorials/amqp-concepts.html" target="_blank" rel="noopener"
&gt;https://www.rabbitmq.com/tutorials/amqp-concepts.html&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Au delà de ça, je ne vais pas vous insister, car d’une part la documentation est plutôt bien faite et comporte plusieurs tutoriels bien sympa, et d’autre part, j’ai vu passer d’autres tutos sur les réseaux récemment. Je vous colle quelques liens sympa pour commencer :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://www.rabbitmq.com/" target="_blank" rel="noopener"
&gt;Le site officiel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.rabbitmq.com/documentation.html" target="_blank" rel="noopener"
&gt;La documentation du site officiel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.rabbitmq.com/getstarted.html" target="_blank" rel="noopener"
&gt;Les tutos en plein de langages pour commencer à bidouiller&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog.eleven-labs.com/fr/rabbitmq-partie-1-les-bases/" target="_blank" rel="noopener"
&gt;Les bases de RabbitMQ sur eleven-labs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="racontes-nous-une-histoire"&gt;Racontes nous une histoire
&lt;/h2&gt;&lt;p&gt;Pour simplifier notre vie, le cluster agit de telle sorte que tous les objets logiques (utilisateur, queue, exchange), où qu’ils soient, sont connus et &lt;em&gt;adressables&lt;/em&gt; depuis tous les membres du cluster. Cependant, une notion importante à comprendre quand on parle de cluster sur RabbitMQ est qu’à un moment donné, &lt;strong&gt;une&lt;/strong&gt; &lt;strong&gt;&lt;em&gt;queue&lt;/em&gt;&lt;/strong&gt; &lt;strong&gt;n’est physiquement présente que sur un serveur&lt;/strong&gt;, même en cluster.&lt;/p&gt;
&lt;p&gt;J’explique : si on adresse une requête au serveur B pour la queue/file 1 qui est sur le serveur A, celui ci redirigera gentiment la requête vers le serveur 1.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/04/RabbitMQ_cluster_redirect.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Pour l’utilisateur / développeur, ça sera transparent, mais pour le sysadmin c’est une autre paire de manches.&lt;/p&gt;
&lt;p&gt;Supposons que pour une raison ou pour une autre, &lt;strong&gt;toutes&lt;/strong&gt; les queues soient hébergées sur un même nœud. Dans ce cas là, toute la charge sera portée par ce serveur et les autres ne feront que passe plat.&lt;/p&gt;
&lt;h2 id="dans-quels-cas-ça-arrive-"&gt;Dans quels cas ça arrive ?
&lt;/h2&gt;&lt;p&gt;Alors vous allez me dire : &lt;em&gt;pfff ya aucune raison que toutes les queues soient sur le même nœud&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Et ben si, yen a même plusieurs ;-)&lt;/p&gt;
&lt;p&gt;Sans vous spoiler un article futur, on peut très rapidement se retrouver avec ce genre de blague lorsqu’on met à jour les serveurs du cluster uns par uns, jusqu’à ce que le dernier serveur se retrouve à supporter l’ensemble de la charge.&lt;/p&gt;
&lt;p&gt;Et là, vous êtes bien embêtés, car vous n’avez pas de moyen de transférer les queues sur plusieurs autres serveurs. On peut toujours les supprimer puis les recréer une par une sur des serveurs distincts, mais niveau répartition de charge, on a vu mieux&amp;hellip;&lt;/p&gt;
&lt;h2 id="et-alors-comment-on-fait-"&gt;Et alors comment on fait ?
&lt;/h2&gt;&lt;p&gt;Il est possible d’indiquer à RabbitMQ qu’il doit &lt;strong&gt;répliquer&lt;/strong&gt; certaines queues sur un nœud en particulier, puis, une fois le contenu de la queue synchronisée, de retirer le serveur initial de la liste des nœuds de cette queue.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/04/RabbitMQ_move_master.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Je vous sens encore sceptiques. « On est pas plus avancés » me direz vous ?&lt;/p&gt;
&lt;p&gt;En effet, il faut encore prendre les queues unes par unes et les déplacer sur un autre nœud puis les supprimer du nœud initial. Oui, sauf que les développeurs de RabbitMQ, conscients du problème, ont créés un plugin pour automatiser tout ça. On en arrive à l’objet de cet article : &lt;strong&gt;rabbitmq-queue-master-balancer&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;RabbitMQ Queue Master Balancer is a tool used for attaining queue master equilibrium across a RabbitMQ cluster installation. The plugin achieves this by computing queue master counts on nodes and engaging in shuffling procedures, with the ultimate goal of evenly distributing &lt;code&gt;queue masters&lt;/code&gt; across RabbitMQ cluster nodes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Traduction : ça permet de répartir nos queues de manière à peu près équitable entre les nœuds (en partant du principe &lt;em&gt;généralement erroné&lt;/em&gt; que la charge est proportionnelle au nombre de queues hébergées par le nœud).&lt;/p&gt;
&lt;h2 id="installation"&gt;Installation
&lt;/h2&gt;&lt;p&gt;RabbitMQ, en plus de tout ce qu’on a dit de chouette à son propos, permet aussi d’être étendu à l’aide de plugins. On peut aller télécharger celui qui nous intéresse sur Github.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;wget https://github.com/Ayanda-D/rabbitmq-queue-master-balancer/releases/download/v0.0.3/rabbitmq_queue_master_balancer-0.0.3.ez
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Point qui n’est pas forcément mis en avant dans le projet &lt;strong&gt;rabbitmq_queue_master_balancer&lt;/strong&gt;, les plugins peuvent être déposés dans 2 dossiers différents. Un commun à toutes nos versions, et un qui change à chaque mise à jour.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;/usr/lib/rabbitmq/plugins&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;/usr/lib/rabbitmq/lib/rabbitmq_server-[version]/plugins/&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vous trouverez plus d’information sur les plugins RabbitMQ et leur fonctionnement au niveau de &lt;a class="link" href="https://www.rabbitmq.com/installing-plugins.html" target="_blank" rel="noopener"
&gt;la page dédiée à leur sujet&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Dans notre cas, le plugin n’est pas dépendant de votre version. On créé donc le dossier pour le contenir, puis on l’y dépose.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo mkdir /usr/lib/rabbitmq/plugins
sudo mv rabbitmq_queue_master_balancer-0.0.3.ez /usr/lib/rabbitmq/plugins/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Comme n’importe quel autre plugin « built-in », on peut maintenant l’activer depuis la ligne de commande habituelle &lt;strong&gt;rabbitmq-plugins&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo rabbitmq-plugins enable rabbitmq_queue_master_balancer
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="utilisation"&gt;Utilisation
&lt;/h2&gt;&lt;p&gt;Voici maintenant un exemple d’utilisation qui va vous permettre de vous familiariser avec l’outil. Tout se passe en ligne de commandes (c’est un peu spartiate). On va demander à &lt;strong&gt;rabbitmqctl&lt;/strong&gt; d’exécuter des fonctions provenant de notre plugins.&lt;/p&gt;
&lt;p&gt;On commence par afficher la répartition actuelle dans notre cluster avec la fonction &lt;strong&gt;report()&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo rabbitmqctl eval &amp;#39;rabbit_queue_master_balancer:report().&amp;#39;
{ok,[{&amp;#39;rabbit@rabbitmq2&amp;#39;,{queues,0}},
{&amp;#39;rabbit@rabbitmq3&amp;#39;,{queues,30}},
{&amp;#39;rabbit@rabbitmq1&amp;#39;,{queues,0}}]}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ici, on voit que toutes les queues se sont retrouvées sur le rabbitmq3 suite à un rolling upgrade.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/01/truestory.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;On lance donc le processus de répartition des queues avec la fonction &lt;strong&gt;go()&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo rabbitmqctl eval &amp;#39;rabbit_queue_master_balancer:go().&amp;#39;
ok
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A partir de là, si vous êtes simultanément connecté sur votre console web d’administration de RabbitMQ, vous verrez en live qu’il s’y passe des choses. En ligne de commande, vous pourrez aussi voir où ça en est avec la fonction &lt;strong&gt;status()&lt;/strong&gt;&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo rabbitmqctl eval &amp;#39;rabbit_queue_master_balancer:status().&amp;#39;
[{process_id,&amp;lt;9157.8313.0&amp;gt;},
{queues_pending_balance,18},
{memory_utilization,284640}]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ici il reste encore 18 queues à re-répartir. Au final, tout devrait rentrer dans l’ordre :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;sudo rabbitmqctl eval &amp;#39;rabbit_queue_master_balancer:report().&amp;#39;
{ok,[{&amp;#39;rabbit@rabbitmq2&amp;#39;,{queues,10}},
{&amp;#39;rabbit@rabbitmq3&amp;#39;,{queues,9}},
{&amp;#39;rabbit@rabbitmq1&amp;#39;,{queues,11}}]}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Les plus tatillons d’entre vous auront sûrement remarqué que nous n’avons pas eu une répartition parfaite de nos 30 queues (10*3). Ceci est voulu, pour une raison de &lt;em&gt;formule mathématique obscure&lt;/em&gt;, explicitée sur le dépôt Github du plugin :&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/04/queue_equilibrium.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a class="link" href="https://github.com/Ayanda-D/rabbitmq-queue-master-balancer" target="_blank" rel="noopener"
&gt;https://github.com/Ayanda-D/rabbitmq-queue-master-balancer&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="et-tu-voudrais-pas-faire-un-playbook-ansible-pour-ça-"&gt;Et tu voudrais pas faire un playbook Ansible pour ça ?
&lt;/h2&gt;&lt;p&gt;Ahah la bonne blague. &lt;em&gt;&lt;strong&gt;BIEN SUR&lt;/strong&gt;&lt;/em&gt; que j’en ai fais un playbook Ansible (&lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=ansible" &gt;parce que je suis fan d’Ansible&lt;/a&gt;).&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;---
- hosts: all
vars:
- queue_master_balancer_version: &amp;#34;0.0.3&amp;#34;
tasks:
- name: &amp;#34;Create /usr/lib/rabbitmq/plugins directory for queue balancer plugin&amp;#34;
file:
path: /usr/lib/rabbitmq/plugins
state: directory
mode: 0755
- name: &amp;#34;Download rabbitmq-queue-master-balancer plugin&amp;#34;
get_url:
url: &amp;#34;https://github.com/Ayanda-D/rabbitmq-queue-master-balancer/releases/download/v{{queue_master_balancer_version}}/rabbitmq_queue_master_balancer-{{queue_master_balancer_version}}.ez&amp;#34;
dest: &amp;#34;/usr/lib/rabbitmq/plugins/rabbitmq_queue_master_balancer-{{queue_master_balancer_version}}.ez&amp;#34;
- name: &amp;#34;Add rabbitmq_queue_master_balancer to the list of enabled plugins&amp;#34;
rabbitmq_plugin:
names: rabbitmq_queue_master_balancer
new_only: yes
state: enabled
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A noter, j’utilise l’option &lt;strong&gt;new_only&lt;/strong&gt; du module &lt;strong&gt;rabbitmq_plugin&lt;/strong&gt; pour éviter de désactiver bêtement les plugins déjà actifs.&lt;/p&gt;
&lt;p&gt;Protip gratuite ;) ça serait balo de désactiver tout le reste.&lt;/p&gt;</description></item></channel></rss>