Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Asynchrone avec Symfony Messenger et Mercure

Asynchrone avec Symfony Messenger et Mercure

Générer des PDF, des CSV, ou faire des traitements lourd lors du traitement d'une requête HTTP impacte lourdement les performances de l'application.

Pour pallier ce problème nous pouvons avoir recours à l'utilisation d'un système de asynchrone. Le composant Messenger sera un super allier pour nous faciliter cette tache.

Cependant, comment prévenir le client que son PDF est prêt ou que son import de données est fini ? Mercure nous simplifiera la tache pour notifier le client en temps réel.

Et si notre site est une SPA, pouvons nous tirer parti de ces composant pour rafraîchir notre application avec seulement 3 lignes de code JS ? Venez le découvrir !

Repository pour la démo

Grégoire Pineau

July 03, 2020
Tweet

More Decks by Grégoire Pineau

Other Decks in Programming

Transcript

  1. Asynchrone avec Messenger et Mercure Symfony Live 2025 - Grégoire

    Pineau - @lyrixx Dev @JoliCode / @redirectionio CoreTeam @Symfony 1
  2. Problème : le mode synchrone • L’utilisateur doit attendre que

    la requête soit traitée 💤 • S’il change de page, l’import sera en échec 💥 • Le nombre de workers PHP (FastCGI ou mod_php) est une ressource limitée 🌤⛈🌪 7
  3. Solution : le mode asynchrone • Le traitement sera relégué

    en arrière-plan ◦ Temps de réponse plus rapide • Par un autre processus ◦ Plus de problème avec FastCGI ou mod_php • Éventuellement sur une autre machine ◦ Distribution du load 8
  4. Faire de l’asynchrone • DX / Ops plus compliqué •

    Les actions ne sont plus “temps réel” ◦ UX dégradée 👎 • Meilleur temps de réponse • Facilite la scalabilité • Gestion des erreurs simplifiée 👍 10
  5. Messenger ? On dispatch un message dans le bus Le

    bus route le message vers un handler Messenger agit comme un “man in the middle” 14
  6. Centraliser tous les messages via un bus, quelles conséquences ?

    • Logger chaque message • Valider les messages • Wrapper chaque handler dans une transaction SQL • Stocker le message quelque part… et ensuite exécuter une commande pour lire et traiter le message • Et bien plus encore, voir la conférence de Tugdual… 17
  7. Il existe de faux transports sync:// Gère les messages de

    manière synchrone (dev / test) in-memory:// Ne dispatch pas les messages aux handlers (test) 22
  8. Des daemons pour les workers en production • Supervision ◦

    SystemD - ou le superviseur de votre OS ◦ Supervisord ◦ Gérer par votre PaaS (Clever Cloud, Upsun, Heroku, …) • Penser à redémarrer les workers à chaque déploiement • Exécuter autant de worker que nécessaire (scaling) ◦ Ne pas ajouter plus de worker si la machine est déjà CPU bounded 37
  9. Monitoring • Il faut monitorer la taille des queues •

    Surtout celle “failed” ◦ Et pourquoi pas faire un écran dans l’admin du site ! ◦ https://github.com/zenstruck/messenger-monitor-bundle 38
  10. Gestion des fichiers • Via la queue • Local •

    NFS / ZFS / XFS / GlusterFS • Distant (S3 Like) 40
  11. Et plus encore • Différents transports ◦ Doctrine ◦ AMQP

    ◦ Redis ◦ Amazon SQS ◦ Beanstalkd ◦ Intégration avec PHP Enqueue ▪ Kafka ▪ Google Pub/Sub (ou via petitpress/gps-messenger-bundle) • Sérialisation de message (JSON) • Middlewares et Event • … 42
  12. Et Voilà ! Merci 🤗 En fait non, il y

    a encore un tout petit peu de boulot 43
  13. Une expérience utilisateur dégradée L’import de données est asynchrone L’utilisateur

    n’a aucun feedback : • Est-ce que l’import est en cours ? • Est-ce que l’import est fini ? • Est-ce que l’import s’est bien terminé ? 45
  14. Les bénéfices des websockets • Communication Full Duplex • Bas

    niveau : contrôle total Les websockets VS SSE ? Les inconvénients des websockets • Bas niveau, donc à implémenter : ◦ Authentification ◦ Reconnexion ◦ Historique des messages “perdus” • Dur à sécuriser • Déprécié par HTTP 2 et 3 ◦ WebTransport 50
  15. Mercure : Un “nouveau” protocole • “Surcouche à SSE” •

    Une spécification sur IEFT (encore en draft) • Full Duplex ◦ Subscribe : SSE ◦ Publish : HTTP POST • Nativement: reconnexion, récupération des messages “perdus”, historique • Sécurisé avec JWT • Conçu pour les scripts avec une courte durée de vie: PHP, FastCGI, Serverless 51
  16. Que faire passer dans mercure ? Plusieurs stratégies s’offrent à

    vous : • Un ID pour que le client refresh la data ? • Du JSON pour le consommer en JavaScript ? • Du HTML ? 61
  17. Connecter SSE et Turbo Turbo peut se connecter à n'importe

    quelle forme de flux pour recevoir et traiter des actions de flux. Une source de flux doit envoyer des messages MessageEvent qui contiennent l'action de flux HTML dans l'attribut data de cet événement. [...] https://turbo.hotwired.dev/reference/streams 67
  18. Oui ! Sans écrire une seule ligne de JS !

    71 Plus besoin de JS ! Block status
  19. Avec React ? • Sérialisez vos DTO / Entités comme

    dans votre API ◦ Avec un Store (redux) ▪ Mettre à jour le store ◦ Avec ReactQuery ▪ Mettre à jour le cache 74
  20. La sécurité • Mercure utilise JWT (JSON Web Token) •

    Le publisher doit être authentifié • Un subscriber ◦ Peut être anonyme (si la configuration l'autorise) ◦ Doit être authentifié pour recevoir du contenu privé • Un update peut cibler une ou plusieurs targets • Deux transports : cookie ou Authorization header 76
  21. Le serveur (hub) • Il existe une implémentation de référence

    (en Go) ◦ Rapide ◦ Fonctionne partout (binaire statique, plugin Caddy, image docker) ◦ HTTP2 et HTTPS (via let’s encrypt) ◦ Support de CORS + CSRF ◦ Cloud native (12Factor app) ◦ Open Source (AGPL) • Il existe au moins une autre implémentation ◦ En JavaScript https://github.com/Ilshidur/node-mercure 78
  22. 84

  23. Conclusion • Messenger ◦ Simple à mettre en place (en

    dev et en prod) ◦ Son utilisation est très simple ◦ Le composant est flexible ◦ Permet de décharger le front au profit de worker • Mercure ◦ Moins simple à mettre en place (en dev comme en prod) ▪ Mais il existe une version managée ◦ Son utilisation est très simple ◦ Donne du feedback à l’utilisateur en temps réel ◦ Améliore la DX 85
  24. Vous avez aimé la démo ? Retrouvez le code sur

    github: lyrixx/async-messenger-mercure 87
  25. Merci Symfony Live 2025 - Grégoire Pineau - @lyrixx Dev

    @JoliCode / @redirectionio CoreTeam @Symfony 88
  26. Des questions ? Symfony Live 2025 - Grégoire Pineau -

    @lyrixx Dev @JoliCode / @redirectionio CoreTeam @Symfony 89