Pourquoi les SSE sont-ils meilleurs que les WebSockets pour la communication en temps réel ?
L’envoi de données en temps réel est nécessaire dans presque toutes les applications modernes. Que ce soit pour créer un flux de tweets, de commentaires, des cours boursiers, un tchat, un système de notifications, etc… De nos jours beacoup de développeurs web optent pour les WebSockets. Dans cet article je soutiendrai qu’utiliser les SSE (“Server-Sent Events”) est préférable dans la plupart des cas.
Ce billet de blog est un article d’opinion. Il est le reflet de mon expérience personnelle en tant de développeur full-stack et ne peut donc être dénué de tout biais ou même d’erreur. J’ai clairement raison, mais n’hésitez pas à me contredire. J’aime les débats :)
WebSockets
L’interface WebSockets permet aux
applications Web de maintenir un canal de communication bidirectionnel avec un
serveur. Bien qu’elles soient une abstraction sur le protocole HTTP, les
connexions WebSockets sont en fait effectuées via leur propre protocole. Il
utilise les schémas d’URL ws
et wss
au lieu de http
et https
. Le
protocole WebSockets fournit un
mécanisme de streaming facile à utiliser et largement disponible depuis sa
création en 2011.
Comment ça marche ?
Un canal WebSockets est initialisé via HTTP. La connexion HTTP est ensuite mise à niveau vers une connexion WebSockets si elle réussit. Ensuite, les données sont transférées via TCP dans les deux sens jusqu’à ce que la connexion soit fermée.
Server-Sent Events
La technologie SSE permet l’envoi de données en temps réel à partir d’un serveur
via une connexion HTTP. Elle a été proposé pour la première fois en 2004 et fait
maintenant partie de la
norme HTML
qui définit un type de contenu HTTP text/event-stream
(en-tête “Content-Type”)
spécifique à cette utilisation.
Comment ça marche ?
Une requête HTTP est effectuée pour une ressource text/event-stream
. La
connexion est maintenue et les événements sont diffusés en continu vers le
client jusqu’à sa fermeture.
Les WebSockets et les SSE sont des technologies concurrentes
Ces deux technologies permettent aux applications Web de recevoir des données en temps réel d’un serveur. Une fonctionnalité qui ne pouvait jusque là pas être implémentée en suivant la norme Web sans une bonne dose de bidouille. La raison étant que le Web a été construit sur un modèle requête-réponse. Dans un environnement Web, un client fait généralement une requête qui est ensuite traitée par un serveur qui envoie une réponse, mettant ainsi fin à l’interaction. Les WebSockets et les SSE résolvent tous deux le même problème.
Pourquoi les WebSockets sont-ils généralement préférés aux SSE ?
Les WebSockets sont une technologie plus récente, puissante et polyvalente que les SSE. Elle présente deux avantages significatifs. Le plus important étant que le protocole permet une communication bidirectionnelle. Les messages peuvent être reçus en temps réel mais également envoyés via le même canal. Les paquets de données réseaux envoyés via WebSockets sont moins lourds que les SSE puisque, une fois l’initialisation effectuée, les données sont directement envoyées via TCP (l’en-tête HTTP n’est donc plus nécessaire). Cela implique que des données binaires peuvent aussi être envoyées de cette façon alors que les SSE ne gèrent que le texte (encodé en UTF-8).
Les SSE sont une bien meilleure solution que les WebSockets
Les avantages mineurs des WebSockets par rapport aux SSE ne devraient pas faire la différence dans la plupart des cas. Supprimer l’en-tête HTTP est une optimisation qui n’aura de sens que dans certains contextes très spécifiques (si des milliers d’évènements sont envoyés par seconde par exemple). De plus, si le streaming de données binaires est absolument nécessaire, le flux peut être encodé en base64 et envoyé sous forme de texte. Enfin, la principale fonctionnalité des WebSockets qui manque aux SSE est complètement redondante dans le contexte Web. Les requêtes HTTP sont exécutées en temps réel par définition puisqu’elles sont initiées par le client. Avant les SSE, ce qui manquait véritablement à la norme HTTP était l’envoi de données à l’initiative du serveur et non à celle du client.
Dans la pratique les WebSockets présentent un inconvénient majeur. Bien que cette technologie repose en partie sur HTTP, elle utilise son propre protocole alors que les SSE font pleinement partie de la norme HTTP. Cela signifie que les SSE sont typiquement bien plus simples à inclure dans l’implémentation d’une API REST que les WebSockets. Il suffit d’ajouter une route HTTP dans un cas alors qu’il faut mettre en place un serveur entièrement distinct dans l’autre. C’est important parce que créer un nouveau serveur implique que certaines fonctionnalités déjà implémentées devront être adaptées voire complètement ré-écrites.
L’authentification est un problème majeur dans ce contexte. Si vous travaillez sur une API, vous disposez probablement déjà d’un système d’authentification des utilisateurs, que ce soit par cookies, JWT ou autre. Donc s’il faut que les fonctionalités en temps réel soient authentifiées (cibler des utilisateurs spécifiques pour une notification, restreindre l’accès à certaines ressources, etc…), vous devrez implémenter un système d’authentification supplémentaire pour le serveur WebSockets. C’est particulièrement problématique car les WebSockets ne permettent pas de le faire au niveau protocolaire contrairement à HTTP. Concrètement l’authentification doit être effectuée via la connexion WebSockets elle-même. Une solution courante est de créer une route HTTP authentifiée pour générer un nonce qui sera envoyé et consommé via la connexion WebSockets dans le premier message. Ce n’est pas idéal.
Le meilleur cas d’utilisation pour les WebSockets est une application Web non authentifiée à très haut débit et qui n’utilise pas HTTP pour communiquer avec son serveur back-end. Ce qui implique également de ne pas utiliser la sémantique HTTP REST (requêtes GET/PUT/POST/DELETE) ou de la réimplémenter. Le moins qu’on puisse dire c’est que ce n’est pas très courant.
Conclusion
Les Server-Sent Events sont plus simples à utiliser et à implémenter que les WebSockets. Puisqu’ils font partie du très courant protocole HTTP, il est bien plus facile d’interagir avec d’autres systèmes via cette méthode (moins de problèmes de pare-feu par exemple). HTTP dispose déjà d’un mécanisme pour envoyer des données en temps réel depuis le serveur. Pourquoi utiliser une autre technologie lorsque l’on travaille sur une application Web ?