Josselin Dionisi - Développeur indépendant

Des actions récurrentes ? Symfony et RabbitMQ pour des événements asynchrones...

ionicons-v5-k Josselin Dionisi 13 févr. 2024
990 lectures Niveau : Confirmé

Bonjour ici ! 😃 cela fait quelques temps qu’on ne s’est pas parlé car beaucoup de choses se font en arrière plan dans la vie d’un développeur freelance. Tiens d’ailleurs c’est un peu ce dont on va parler aujourd’hui, oui oui des choses en arrière plan.

Je vais vous présenter RabbitMQ un outil qui peut être très facilement couplé à Symfony et qui crée vraiment un combo redoutable de performances et d’efficacité. J’ai eu besoin de l’implémenter pour un petit outil maison me permettant de programmer des publications sur les réseaux sociaux. 😁 

Que sont les messages et les bus ?

Avant de rentrer dans le vif du sujet, il faut que je vous explique brièvement ce qu’est un message.

“Un message ? Comme un SMS ? Mais tout le monde voit ce qu’est un message en 2024 !”

Alors oui mais pas tout à fait. Ici on parle de message au sein du composant Messenger de Symfony.

Dans ce contexte, les messages peuvent être tout ce que vous souhaitez, des simples chaînes de texte à des objets complexes représentant une tâche à effectuer. Ils sont ensuite transportés par un bus qui quant à lui, agit comme un système de distribution, acheminant les messages vers les bons destinataires, appelés handlers ou gestionnaires.

En quoi RabbitMQ peut aider à l’optimisation de scripts PHP ?

“Ok donc on peut envoyer des messages mais quel intérêt ?”

Imaginez que vous ayez une tâche récurrente à effectuer qui va contenir plusieurs messages. Au hasard prenons l’exemple d’un outil qui permettrait de programmer des publications sur les réseaux sociaux.

Vous pouvez donc avoir 15 publications Instagram, 30 tweets, etc à publier à 18h pour une multitude de comptes différents.

Le problème ? Cela risque de demander beaucoup de ressources, surtout si les publications contiennent des fichiers à uploader, sans compter le nombre de requêtes API qui peuvent être plus ou moins lourdes.

Si vous êtes un développeur chevronné vous savez que PHP est un langage monothread, il traite tout en une seule fois dans l’odre d’exécution de son code.

C’est exactement dans ce cas que RabbitMQ a tout son intérêt car vous allez pouvoir déléguer ces tâches de façon asynchrone. L’une sera indépendante de l’autre donc vos publications ne seront pas bloquées lorsqu’une plus lourde sera en cours de traitement. Vous suivez ?

Comment mettre en place une instance RabbitMQ ?

“En effet ça a l’air intéressant mais c’est compliqué à mettre en place j’imagine ?”

Et bien pas du tout ! 😊

En fait Symfony intègre déjà de quoi faire du Message Queuing (oui c’est le nom exact de ce principe) avec RabbitMq. En suivant la documentation du lien précédent, vous arriverez donc facilement à connecter les deux. Je vous conseille comme d’habitude d’exécuter un container Docker pour RabbitMQ pour plus de simplicité. Il vous faudra également activer l’extension AMQP de PHP.

Une fois que les deux sont connectés ensemble il va falloir créer 2 classes dans Symfony. L’une qui va correspondre au message que vous souhaitez envoyer. A la manière d’une Entité Symfony vous pouvez y mettre des attributs et des fonctions permettant de les récupérer ailleurs.

Lorsque vous allez lancer votre script de publications, vous allez donc créer un objet message du type de cette classe, par exemple Publication.

Ensuite il vous faut une classe de handler pour gérer ces messages et savoir quoi en faire. Pour nous le but ici serait de faire nos appels à l’API et toutes les tâches lourdes nécessaires à notre application. C’est en effet cette partie qui va être envoyée et déléguée à RabbitMQ.

“Ok super j’ai mes deux classes et je parviens à les faire fonctionner mais après je dois faire quoi ?”

Et bien si tout est bien configuré vous ne devriez plus rien à voir à faire si ce n’est de lancer les commandes pour votre script puis pour que RabbitMQ se mette effectivement à s’en occuper, ce qu’on appelle “consommer les messages” et qui se traduit par cette commande Symfony : bin/console messenger:consume async

Comment suivre le process de RabbitMQ et les messages consommés ?

Il existe un plugin RabbitMQ justement fait pour cela qui s’appelle Management celui-ci vous offre une interface graphique permettant de suivre ce qui se passe dans votre gestionnaire de messages. Voici quelques exemples :

La dashboard de RabbitMQ

Ici on peut voir qu’une instance est en attente avec le statut “ready”. Elle a besoin que la commande messenger:consume soit lancée pour être executée.

Commande symfony : Messenger;consume

Le post a maintenant été publié

Tweet publié automatiquement

Effectivement notre publication est désormais en ligne ! 😀

Conclusion : L'art de bien communiquer

Pour résumer, je dirais que RabbitMQ est la meilleure façon de transformer la gestion des messages en une partie de plaisir simple et intuitive plutôt qu'en un casse-tête. La gestion des queues ainsi que des erreurs vous permet sereinement de déléguer les actions en gardant une part de contrôle. 

Pensez cependant à bien suivre la documentation pour une mise en prod car il sera sans doute nécessaire d’avoir des outils sur votre serveur pour suivre les process, couper les commandes à certains moments etc. 

Voilà, vous avez maintenant tout ce qu’il faut pour passer vos applications au stade supérieur 😊