Bien configurer sa plateforme pour gérer les Web Sockets

Gregory EVE
Smile with WSO2
Published in
5 min readJan 13, 2021

Au secours mon WSO2 Analytics dashboard n’affiche rien! Vous avez bien suivi la documentation et pourtant cela ne veut pas fonctionner. Pas de panique c’est bien souvent car il utilise du webSocket et que cela nécessite des configurations supplémentaires de votre infrastructure.

C’est quoi les Web Sockets?

C’est un protocole de communication qui permet de créer des canaux de communication bidirectionnelle (full-duplex) sur une simple connexion TCP.

C’est-à-dire qu’il permet a un client et a un serveur d’envoyer à l’autre des messages directement à travers ce canal sans requête ou connexion supplémentaire. Si vous avez besoin d’envoyer des messages en “temps-réel” dans les deux sens, comme une application de chat ou un jeu multi-joueur, c’est le bon protocole pour ça.

Histoire

Lors de la rédaction des spécifications de HTML5, au sein du W3C et du WHATWG, est apparu en 2008 le terme TCPConnection pour désigner une API de socket basée sur TCP. Ce nom temporaire fut remplacé par la suite par Web Socket.

En 2010 la spécification est transférée à l’IETF pour donner naissance fin 2011 au standard RFC 6455. Celui-ci a été complété 3 fois depuis lors:

Comment ça marche?

Web Socket est un protocole applicatif de niveau 7 du modèle OSI, comme HTTP. Il repose sur TCP, un protocole de transport de niveau 4 du modèle OSI.

> HTTP 1.1

Pour initier une connexion Websocket (Handshake) il faut passer par une connexion HTTP. Non vous avez bien lu! Dans la version 1.1 (RFC 7230) du protocole HTTP est apparu la notion de UPGRADE. Son but est de permettre de monter de version le protocole en cours d’utilisation (par exemple ajouter une couche TLS) ou de changer de protocole de communication. Peu utilisé jusqu’à présent, c’est le moyen encouragé par les auteurs du standard pour permettre de communiquer sur le même port que HTTP que vous utilisez couramment.

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: mqtt, amqp, xmpp
Sec-WebSocket-Version: 13
Origin: http://example.com

Vous pouvez ajouter optionnellement d’autres headers:

  • Sec-WebSocket-Extensions pour ajouter des extensions protocolaires :
    - permessage-deflate : RFC 7692 pour compresser les messages
    - bbf-usp-protocol : USP pour gérer, suivre, mettre à jour et contrôler des objets connectés
  • Sec-WebSocket-Key : un code de confirmation client de la volonté de réaliser ce changement (ajouté automatiquement par votre navigateur)
  • Sec-WebSocket-Protocol : une liste de préférence des sous protocoles que vous souhaitez utiliser. Pour avoir la liste des possibilités : WebSocket Subprotocol Name Registry
  • Sec-WebSocket-Version : version du protocole que le client souhaite utiliser. Normalement 13, qui est la version du standard.

En réponse le serveur renvoi un code 101 qui déclenche le changement de protocole.

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: mqtt

> HTTP 2

Ce mécanisme n’est plus possible en HTTP 2 à cause de sa nature multiplexée. L’idée est ici d’au lieu d’avoir une connexion dédiée de réserver un stream dans la connexion existante à cet usage et ainsi de bénéficier de toutes les avancées de HTTP 2.

Pour cela WebSocket, dans la RFC 8441, étend le fonctionnement de la méthode HTTP CONNECT en ajoutant des pseudo-headers.

> HTTP 3

Ou anciennement HTTP over QUIC.

Là vous en demandez beaucoup! Le standard HTTP 3 n’est pas encore finalisé et les premiers essais d’implémentation dans les navigateurs, frameworks et serveurs web sont en cours. Mais il est vrai que c‘est mal engagé car HTTP 3 est basé sur UDP et pas TCP!

Alternatives

> Server-Sent Events

Server-Sent events est une technologie définie par le WHATWG qui permet à un client de recevoir des mises à jour automatique depuis un serveur via une connexion HTTP. Vous réaliser un appel GET sur une ressource du serveur et celui-ci vous répond avec des messages avec un Content-Type text/event-stream.

Son lancement a été laborieux. La première expérimentation de cette technologie date de 2006 et n’est devenu une recommandation du W3C qu’en 2015. Microsoft ne l’a jamais implémenté dans ses navigateurs Internet Explorer puis Edge.

Les 3/4 du temps, c’est de cette technologie dont vous avez besoin, qui est beaucoup plus légère et accessible que WebSocket.

> Long Polling

Le long polling c’est la technique historique pour envoyer des événements du serveur vers le client. C’est l’idée simple que le serveur attend qu’il a quelque chose à dire avant de vous retourner une réponse.

Ce pattern a un avantage majeur c’est qu’il fonctionne partout mais les cas d’erreurs et son implémentation sont entièrement à votre charge. A choisir préférez donc le SSE.

Pour plus d’information je vous renvoie vers l’excellent article de Stanko Krtalić Rusendić : Do you really need WebSockets?

Configuration de votre reverse proxy

Mais revenons à notre plateforme WSO2, quel est le problème?

Si vos requêtes passent par un reverse-proxy celui-ci en général ne traite pas l’entête UPGRADE et ne sait pas traiter de tunnel par défaut, il faut le configurer pour.

Apache Server

Il vous faut activer les modes :

  • proxy
  • proxy_http
  • proxy_wstunnel

et configurer votre Virtual Host comme ceci:

<VirtualHost *:80>
ServerName www.monsite.com

RewriteEngine on
RewriteCond ${HTTP:Upgrade} websocket [NC]
RewriteCond ${HTTP:Connection} upgrade [NC]
RewriteRule .* "ws:/localhost:8080/$1" [P,L]

ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
ProxyRequests off
</VirtualHost>

Nginx

http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

upstream websocket {
server localhost:8080;
}

server {
listen 80;
location / {
proxy_pass http://websocket;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
}
}
}

HaProxy

global
maxconn 4096

defaults
mode http
balance roundrobin
option redispatch
option forwardfor

timeout connect 5s
timeout queue 5s
timeout client 50s
timeout server 50s

frontend http-in
bind *:80
default_backend servers

acl is_websocket hdr(Upgrade) -i WebSocket
#all host starting with 'ws' are considered as websocket
acl is_websocket hdr_beg(Host) -i ws

# The connection to use if 'is_websocket' is flagged
use_backend websockets if is_websocket

backend servers
server server1 [Address]:[Port]
server server2 [Address]:[Port]

backend websockets
balance source
option http-server-close
option forceclose
server ws-server1 [Address]:[Port] weight 1 maxconn 1024 check
server ws-server2 [Address]:[Port] weight 1 maxconn 1024 check

--

--

Gregory EVE
Smile with WSO2

Solution Architect at Smile, french lover and open source supporter. Integrate, Search, Leverage and Secure your data what else?