Cet article est un compte rendu de la conférence intitulée « Le Streaming d'APIs : pourquoi et comment transformer vos APIs statiques en données temps réel ? » présentée par Audrey Neveu au cours de la 6ème édition de Devoxx France qui s'est déroulée au Palais des Congrés.
Ce post est en 2 parties pour traiter les 2 questions abordées au cours la conférence :
Pourquoi est-il important de donner aux utilisateurs une vision "temps-réel" de leur données dans le streaming d'APIs ?
Quels sont les moyens pour parvenir à transformer vos APIs statiques en données temps réel ?
Pourquoi est-il important de donner aux utilisateurs une vision "temps-réel" de leur données dans le streaming d'APIs ?
De nos jours, pour rendre nos applications toujours plus attractives, il faut, en plus d'une UX attrayante, des données à jour en temps réel. Ces dernières permettent en effet de nourrir la "peur de manquer quelque chose" ou FOMO (Fear Of Missing Out), utilisée par les géants du web comme un levier sur leurs utilisateurs pour les inviter à revenir fréquemment sur leurs applications.
Mais qu'est-ce que le temps réel ? Pour répondre à cette question, on a étudié les ordres de grandeur de 2 notions :
le temps de réaction : c'est le temps moyen de nos réflexes de base qui se situe entre 100 et 500ms,
le temps d'interaction : il constitue notre temps à interagir avec l'extérieur. Pour le quantifier on s'est intéressé à 3 éléments :
le temps de réponse à une question fermée : c'est le temps nécessaire pour répondre à une question dont la réponse est de type oui/non, il se situe à 100ms
le temps de réponse à une question ouverte : c'est le temps nécessaire pour construire une réponse plus complexe qui se trouve aux alentours de 500ms
la mémoire sensorielle : c'est le premier bus d'entrée de la mémoire court terme, l'ordre de grandeur se situe entre 200 et 500ms.
Ces ordres de grandeur ont un impact réel sur l'activité des applications, voici deux exemples pour l'illustrer. En 2009, on a observé que chez Amazon, une latence de plus de 100ms implique une baisse de 1% de ventes (source ici). Chez Google, 500ms en plus pour afficher une page provoque une perte de 20% du trafic (source ici).
Une échelle de tolérance a donc été établie en fonction du temps de réponse :
s'il est inférieur à 1s, c'est ok, l'effet Wahoo est garanti et vos utilisateurs sont satisfaits (en dessous de 500ms, ne cherchez pas à optimiser, le cerveau humain ne fera pas la différence),
à 4s, les utilisateurs desktop vous lâchent (ils ont en général une bonne connexion),
à 6s ce sont les utilisateurs mobiles qui partent, ils sont un peu plus tolérants mais là, s’en est trop,
au delà de 10s, ne cherchez pas, plus personne ne consulte votre site.
Mais quels sont donc les différents moyens à notre disposition pour faire du temps réel avec nos API REST ? Je vais détailler les 6 principales solutions en suivant les 3 points suivants :
Polling & Long Polling
Webhooks & Publish-subscribe
Web-Sockets VS Server-Sent Events
Quels sont les moyens pour parvenir à transformer vos APIs statiques en données temps réel ?
Polling & Long Polling
Le Polling
Alors celui-ci, c'est le plus connu. Pour savoir si mes données ont changé, je demande à mon serveur. Donc si je veux être à jour à chaque seconde, je demande à mon serveur si mes données ont changé toutes les secondes. On voit vite les limites de cette méthode lorsqu'on veut être à jour très fréquemment.
Le Long Polling
Pour éviter la multiplication du nombre de requêtes (et oui, nous sommes dans un monde ou chaque requête a un coût), on a imaginé le Long Polling. Cette variante consiste à garder la connexion avec le serveur jusqu'au prochain changement. En clair, un thread est occupé jusqu'à la notification d'un événement et on reste sur du séquentiel, ce qui n'est pas vraiment le comportement voulu notamment si vous commencez à multiplier les sources de données.
Webhooks & Publish-subscribe
Les Webhooks
Cette méthode consiste à créer une url de callback chez le client et à l’enregistrer sur le server, pour que celui-ci fasse un appel lors du traitement de l’événement. Pour illustrer ce fonctionnement, on peut prendre l'exemple de Github. La plateforme nous donne la possibilité de renseigner une url de callback à appeler dès qu'un push est effectué sur le server afin de lancer, par exemple, une intégration continue.
Fonctionnement des Webhooks (source ici)
Publish-subscribe
Pour éviter à l'utilisateur l'enregistrement manuel d'une URL de callback sur le serveur, le mécanisme Publish-subscribe a été inventé. Il repose sur l'interaction entre les Publishers (éditeurs) qui créent des messages associés à une catégorie, et les Subscriber (abonnés) qui souscrivent aux catégories qui les intéressent et ne reçoivent que les messages des catégories auxquelles ils sont abonnés (via la communication d'url de callback). Ce mécanisme permet de mettre en place facilement des abonnements à des flux d'information, des systèmes de workflow ou encore des notifications événements. Si vous avez envie de tenter l'aventure, voici plusieurs liens qui pourront vous aider à l'implémenter :
PubSubHubHub : évoqué dans la conférence, c’est un protocole de communication basé sur ce mécanisme,
HTTP Subscriptions Specification : c'est une spécification pour utiliser ce mécanisme avec de l'HTTP,
REST Hooks : ce n'est pas une spécification, mais une collection de patterns (si si, il faut le souligner) pour utiliser les webhooks en mode Publish-subscribe.
Description du mécanisme Publish-subscribe (source ici)
Les 2 approches précédentes sont beaucoup plus efficaces que l'approche Polling/Long Polling mais elles nécessites tout de même que le client ait la possibilité d'exposer une url que le serveur peut appeler et ce n'est pas toujours le cas/l'approche la plus simple.
WebSocket VS Server-Sent Events
Pour cette dernière partie, je vais utiliser un tableau comparatif pour mettre en avant les différences entre deux technologies qui permettent au serveur de notifier directement le client lors d'un changement sans passer par une url de callback : les très connus Web-Sockets et les méconnus (et pourtant très intéressants) Server-Sent Events. Vous verrez, je n’ai pas du tout essayé d’être objectif.
WebSocket Server-Sent event Date de création 2008 2006 (tiens c'est plus vieux, pourtant je n'en ai jamais entendu parlé...) Sens Bi-directionnel Uni-directionnel Format supporté Texte et binaire Texte seulement (JSON ok) Protocole A un protocole propre (basé sur TCP). Il vous faudra donc reconfigurer vos proxies et des loud balancers (si ils le supportent) => Repose sur HTTP : il faut seulement ajouter un header "accept text/event-stream", on n'a donc pas besoin de reconfigurer nos servers puisque ça fonctionne en HTTP/1 et HTTP/2 Structure des messages Format de message libre (à vous de le créer)
Plusieurs champs :
data : 1 ou plusieurs ligne de texte/json qui commence par data
id : un identifiant
event : le nom de l’événement qui sera utilisé pour catcher l’événement côté client
retry : le nombre de retry
Gestion des pertes de connexion pas de mécanisme built-in Timeout, retry et utilisation du champ id pour connaître le dernier id successful et repartir depuis cet événement Support Tous les navigateurs Tous les navigateurs modernes :
pour ie vous pouvez utiliser les polyfills
pour edge c'est "under consideration..." donc là...
Benchmark sur le chargement de 500 tweet sur la page Birdwatch (source ici)
Safari : 16 seconds
Chrome: 8 seconds
Firefox: 8 seconds
Safari: 7 seconds
Chrome: 5 seconds
Firefox: 6 seconds
Allez, je vous vois venir, mais comment diable suis-je passé à côté de cette merveille ? On a vu que les Server-Sent Events sont apparus en 2006 et ne sont pas supportés par ie. Mais qui donc était le navigateur avec la plus grande par de marché en 2006 ? Allez, je vous laisse terminer le raisonnement tout seul. De plus, les WebSockets ont d’abord été utilisés dans les chats et jeux vidéos (pour lesquels on avait réellement besoin de transmettre de la data). Lorsqu'on a voulu faire du temps réel dans les appli, on a très vite opté pour ce mécanisme qui était déjà répandu.
En conclusion, pour choisir entre WebSockets et Server-Sent Events, tout dépend bien évidement de votre cas d'utilisation. Mais si votre besoin est seulement
de pousser de la donnée "text/json" du server vers le client
d'envoyer les données qui peuvent être poussées par une requête POST du client vers le server,
ne cherchez plus, les Server-Sent Events sont tout indiqués (vous trouverez ici un super tuto pour coder vos propres SSE).
Voilà, j’espère que vous êtes maintenant plus au fait de toutes les techniques pour intégrer du temps-réel dans vos APIs et que vous serez en mesure de choisir celle qui correspondra à votre cas d’usage.