Par contre nous n’avions pas vu comment configurer de nouveaux exchanges, de nouvelles queues ou définir de nouveaux binding. Remédions à cela!
Pour réaliser une configuration, on peut utiliser l’interface web permettant de “jouer” et faire une config et des tests rapide. Par contre, il est évident que cela manque de reproductibilité. Il faut donc une approche et quelques outils.
D’un côté pour automatiser, généralement on passe pas une interface CLI (où via une api REST, mais on ne le fera pas ici) et justement, on à de la chance car RabbitMQ propose des outils de configuration et de gestion dont entre autre l’outil “rabbitmqadmin” qui permet l’ajout, la suppression des exchanges, queues et binding.
Pour faire ce genre de chose rien de plus simple, pour créer un exchange par exemple:
1 | rabbitmqadmin declare exchange --host=$RMQ_HOST -u $USER -p $PWD name=$exchange_name durable=true type=$exchange_type |
Pour créer une queue:
1 | rabbitmqadmin declare queue --host=$RMQ_HOST -u $USER -p $PWD name=$queue_name durable=true |
Et finalement créer un binding:
1 | rabbitmqadmin declare binding --host=$RMQ_HOST -u $USER -p $PWD source=$exchange_name destination=$queue_name $args |
Et la vous allez dire oui c’est cool mais autant ça peut aider de faire ca en ligne de commande mais mon rabbitmq, il est conteneurisé, du coup ca saoule d’aller se connecter dessus à la main pour aller y jouer mes commandes (surtout que rabbitmqadmin n’est plus dans les dernière version conteneurisé de RabbitMQ….).
Comment faire? et bien nous allons exploiter un pattern de conception propre à docker. Celui de lancer un conteneur (identique où non) à la durée de vie courte qui realisera l’initialisation de notre Message Broker préféré.
Ce pattern est simple il utilise un container contenant nos outils donc le scripts de démarrage est le script d’init que l’on souhaite appliquer sur un autre conteneur cible.
En utilisant dans notre cas le conteneur “softonic/rabbitmqadmin”, nous aboutissons alors à une conf docker-compose telle que:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | version: "3" services: rabbitmq: container_name: rabbitmq image: bitnami/rabbitmq:latest environment: RABBITMQ_USERNAME: user RABBITMQ_PASSWORD: password ports: - "15672:15672" init-rabbitmq: container_name: init-rabbitmq image: softonic/rabbitmqadmin environment: RABBITMQ_USERNAME: user RABBITMQ_PASSWORD: password volumes: - ./:/home:Z depends_on: - rabbitmq command: "/home/test.init.sh" |
Maintenant il reste à faire exécuter nos initialisations comme on le ferait avec script d’init classique (en gardant en tête que l’on fait ça à travers le réseau docker….) Ainsi dans notre cas, on veut construire des exchanges/queues/binding à la volée. On va donc se faire une fonction shell incluant ces trois actions simultanée:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | config_flux() { local exchange_name=$1 local queue_name=$2 local exchange_type=$3 local args="" if [ "$4" != "" ] then args="routing_key=$4" fi echo "Declare exchange $exchange_name with type=$exchange_type and queue $queue_name with $args" rabbitmqadmin declare exchange --host=$RMQ_HOST -u $USER -p $PWD name=$exchange_name durable=true type=$exchange_type rabbitmqadmin declare queue --host=$RMQ_HOST -u $USER -p $PWD name=$queue_name durable=true rabbitmqadmin declare binding --host=$RMQ_HOST -u $USER -p $PWD source=$exchange_name destination=$queue_name $args } |
Et et…. ca marche pas! Quoi! c’est quoi ce bordel! Non bien sur que ca marche pas car on à mis une dépendance de démarrage des conteneur entre eux… mais quand le script de configuration s'exécute, rien ne dit que RabbitMQ, lui a correctement démarré où du moins qu’il a finit sa phase d’init. Il nous faut donc nous mettre en attente de son démarrage avant de lancer la phase d’init.
Rien de plus simple, RabbitMQ comme de nombreux outils modernes intègre un healthcheck qui passe évidemment à OK quand il est prêt. On va donc ajouter une fonction au script pour interroger ce healthcheck.
1 2 3 4 5 6 7 8 9 10 11 | waiting_rabbitmq_started() { local state="nok" while [ "$state" != "ok" ] do echo "http://$USER:$PWD@$RMQ_HOST:15672/api/healthchecks/node" state=$(expr $(curl -G "http://$USER:$PWD@$RMQ_HOST:15672/api/healthchecks/node") : ".*:.\(..\).*") echo "$state" sleep 1s done } |
Il ne reste alors plus qu’à appeler ces fonctions dans notre script pour définir une configuration qui s’appliquera à chaque démarrage
1 2 3 4 5 6 7 | waiting_rabbitmq_started config_flux "myExchangeA" "myQueueA" "direct" "flux1" config_flux "myExchangeA" "myQueueB" "direct" "flux2" config_flux "myExchangeB" "myQueueA" "topic" "flux1.*" config_flux "myExchangeB" "myQueueB" "topic" "*.flux2" |
On finit du coup tout ça en lançant notre docker-compose préféré et on regarde les logs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | $ docker logs init-rabbitmq http://user:password@rabbitmq:15672/api/healthchecks/node % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0curl: (7) Failed to connect to rabbitmq port 15672: Connection refused expr: syntax error: unexpected argument ‘.*:.\\(..\\).*’ [...] http://user:password@rabbitmq:15672/api/healthchecks/node % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 15 100 15 0 0 127 0 --:--:-- --:--:-- --:--:-- 127 ok Declare exchange myExchangeA with type=direct and queue myQueueA with routing_key=flux1 exchange declared queue declared binding declared Declare exchange myExchangeA with type=direct and queue myQueueB with routing_key=flux2 exchange declared queue declared binding declared Declare exchange myExchangeB with type=topic and queue myQueueA with routing_key=flux1.* exchange declared queue declared binding declared Declare exchange myExchangeB with type=topic and queue myQueueB with routing_key=*.flux2 exchange declared queue declared binding declared |
Cool, si on vérifie via l’IHM web, la conf est bien creer… Parfait. il ne reste alors plus qu’à utiliser.
Références:
[1] https://un-est-tout-et-tout-est-un.blogspot.com/2020/02/rabbitmq.html[2] https://www.rabbitmq.com/management-cli.html
[3] https://hub.docker.com/r/softonic/rabbitmqadmin
Aucun commentaire:
Enregistrer un commentaire