Asynchrone avec Symfony Messenger et Mercure

Asynchrone avec Symfony Messenger et Mercure

7602f2751868682b296171f58589c851?s=128

Grégoire Pineau

July 03, 2020
Tweet

Transcript

  1. Asynchrone avec Messenger et Mercure AFUP Day Tours 2020 -

    Grégoire Pineau - @lyrixx Dev @JoliCode CoreTeam @Symfony
  2. Qu’est ce que l’asynchrone ? Pourquoi faire de l’asynchrone ?

    Prenons un exemple
  3. Démo : Un écran d’import de CSV

  4. Un chargement synchrone Problème : 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 ⛈ Solution : mode asynchrone • Le traitement sera relégué en arrière plan • Par un autre processus : plus de problème avec FastCGI ou mod_php • Éventuellement sur une autre machine
  5. Problème : mode synchrone

  6. Solution : un traitement asynchrone

  7. Faire de l’asynchrone • Meilleur temps de réponse • Facilite

    la scalabilité • Gestion des erreurs simplifiée • DX / Ops plus compliqué • Les actions ne sont plus “temps réel” • UX dégradée
  8. En route vers l’asynchrone

  9. Point de départ

  10. De la qualité ! Un service “CsvImporter”

  11. Symfony Messenger Un composant pour faire de l'asynchrone

  12. Messenger ? • Message Bus ◦ Command Bus ◦ Event

    Bus ◦ Query Bus ◦ Oui Bus (Merci Damien )
  13. 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. bin/console make:message CsvUploaded

  15. Dispatch du message dans le Bus

  16. 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
  17. Les Transports

  18. Les transports : où lire / écrire les messages

  19. Configuration

  20. Le Routing

  21. Le routing

  22. Gérer les messages dans la queue (worker)

  23. L’upload n’est plus effectué

  24. Le message est dans la queue

  25. bin/console messenger:consume

  26. ET VOILÀ ! Merci En fait non, il y a

    encore un tout petit peu de boulot
  27. Travailler avec les workers

  28. Des daemons pour les workers en production • SystemD -

    ou le superviseur de votre OS • Supervisord • Gérer par votre PaaS (Symfony Cloud, Heroku, Clever Cloud, …) Pensez à redémarrer les workers à chaque déploiement Exécuter autant de worker que nécessaire (scaling) Ne pas ajouter plus de worker sur une machine si elle est déjà CPU bounded
  29. Les options

  30. Échecs et nouvelles tentatives

  31. En cas d’erreurs

  32. Transport d’échec

  33. De nouvelles commandes

  34. De nouvelles commandes

  35. Faux transports

  36. Il existe de faux transports • sync:// Gère les messages

    de manière synchrone (dev) • in-memory:// Ne dispatch pas les messages aux handlers (test)
  37. Et ensuite ?

  38. Quelques remarques • Gestion des fichiers : local, NFS, distant,

    ou via la queue ? • Un message peut-il publier à son tour un message ? • Il faut monitorer la taille des queues, surtout celle “failed” ◦ Et pourquoi pas faire un écran dans l’admin du site
  39. Et plus encore • Intégration avec PHP Enqueue ◦ Kafka

    ◦ Amazon SQS ◦ Google Pub/Sub • Serialization de message • Middlewares et Event • Envelopes & Stamps • ApiPlatform Integration
  40. Démo : Pas de feedback !

  41. Une expérience utilisateur dégradée Comme 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é ? Il faut donner un feedback à l’utilisateur en temps réel
  42. Mercure Un serveur pour donner du feedback

  43. Démo : Du feedback !

  44. Comment pousser de la donnée vers le client ?

  45. 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” • Déprécié par HTTP 2 et 3 • Dur à sécuriser
  46. Mercure : Un nouveau protocole • Une spécification sur IEFT

    (encore en draft) • Full Duplex ◦ Publish : HTTP POST ◦ Subscribe : SSE • Nativement: reconnexion, récupération des messages “perdus”, historique • Auto découvrable : fait pour REST & GraphQL • Sécurisé avec JWT • Conçus pour les scripts avec une courte durée de vie: PHP, FastCGI, Serverless • Support du chiffrage End2End
  47. Il existe un polyfill pour IE 5.5+

  48. Mercure : son workflow

  49. Comment publier avec Symfony

  50. Configuration de Symfony

  51. Publier sur le hub

  52. Un UUID pour l’import

  53. Comment consommer depuis un navigateur

  54. Connexion au Hub Mercure en JavaScript

  55. Lecture des messages

  56. Sécurité

  57. 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 target • Deux transports : cookie ou Authorization header
  58. Le serveur (hub)

  59. Le serveur (hub) • Il existe une implémentation de référence

    (en Go) ◦ Rapide ◦ Fonctionne partout (binaire statique et docker) ◦ HTTP 2 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
  60. Conclusion

  61. None
  62. Conclusion • Messenger ◦ Simple à mettre en place (en

    dev et en prod) ◦ Son utilisation est facile ◦ Le composant est flexible ◦ Permet de décharger le front au profit de worker ◦ Le composant est stable • Mercure ◦ Simple à mettre en place (en dev et en prod) ◦ Il existe une version managée ◦ Donne du feedback à l’utilisateur ◦ Améliore la DX
  63. Vous avez aimé la démo ? Retrouver le code sur

    github : https://github.com/lyrixx/async-messenger-mercure
  64. Merci AFUP Day Tours 2020 - Grégoire Pineau - @lyrixx

    Dev @JoliCode CoreTeam @Symfony