$30 off During Our Annual Pro Sale. View Details »

Asynchrone avec Symfony Messenger et Mercure

Asynchrone avec Symfony Messenger et Mercure

Grégoire Pineau

July 03, 2020
Tweet

More Decks by Grégoire Pineau

Other Decks in Programming

Transcript

  1. Asynchrone avec Messenger
    et Mercure
    AFUP Day Tours 2020 - Grégoire Pineau - @lyrixx
    Dev @JoliCode
    CoreTeam @Symfony

    View Slide

  2. Qu’est ce que l’asynchrone ?
    Pourquoi faire de l’asynchrone ?
    Prenons un exemple

    View Slide

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

    View Slide

  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

    View Slide

  5. Problème : mode synchrone

    View Slide

  6. Solution : un traitement asynchrone

    View Slide

  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

    View Slide

  8. En route vers l’asynchrone

    View Slide

  9. Point de départ

    View Slide

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

    View Slide

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

    View Slide

  12. Messenger ?
    ● Message Bus
    ○ Command Bus
    ○ Event Bus
    ○ Query Bus
    ○ Oui Bus (Merci Damien )

    View Slide

  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”

    View Slide

  14. bin/console make:message CsvUploaded

    View Slide

  15. Dispatch du message dans le Bus

    View Slide

  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

    View Slide

  17. Les Transports

    View Slide

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

    View Slide

  19. Configuration

    View Slide

  20. Le Routing

    View Slide

  21. Le routing

    View Slide

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

    View Slide

  23. L’upload n’est plus effectué

    View Slide

  24. Le message est dans la queue

    View Slide

  25. bin/console messenger:consume

    View Slide

  26. ET VOILÀ !
    Merci
    En fait non, il y a encore un tout petit peu de boulot

    View Slide

  27. Travailler avec les workers

    View Slide

  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

    View Slide

  29. Les options

    View Slide

  30. Échecs et nouvelles tentatives

    View Slide

  31. En cas d’erreurs

    View Slide

  32. Transport d’échec

    View Slide

  33. De nouvelles commandes

    View Slide

  34. De nouvelles commandes

    View Slide

  35. Faux transports

    View Slide

  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)

    View Slide

  37. Et ensuite ?

    View Slide

  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

    View Slide

  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

    View Slide

  40. Démo : Pas de feedback !

    View Slide

  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

    View Slide

  42. Mercure
    Un serveur pour donner du feedback

    View Slide

  43. Démo : Du feedback !

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  47. Il existe un polyfill pour IE 5.5+

    View Slide

  48. Mercure : son workflow

    View Slide

  49. Comment publier avec Symfony

    View Slide

  50. Configuration de Symfony

    View Slide

  51. Publier sur le hub

    View Slide

  52. Un UUID pour l’import

    View Slide

  53. Comment consommer depuis un
    navigateur

    View Slide

  54. Connexion au Hub Mercure en JavaScript

    View Slide

  55. Lecture des messages

    View Slide

  56. Sécurité

    View Slide

  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

    View Slide

  58. Le serveur (hub)

    View Slide

  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

    View Slide

  60. Conclusion

    View Slide

  61. View Slide

  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

    View Slide

  63. Vous avez aimé la démo ?
    Retrouver le code sur github :
    https://github.com/lyrixx/async-messenger-mercure

    View Slide

  64. Merci
    AFUP Day Tours 2020 - Grégoire Pineau - @lyrixx
    Dev @JoliCode
    CoreTeam @Symfony

    View Slide