BLOG | NGINX

NGINX comme proxy WebSocket

NGINX-Partie-de-F5-horiz-black-type-RGB
Vignette de Rick Nelson
Rick Nelson
Publié le 16 mai 2014

Le protocole WebSocket permet de créer des applications Web qui prennent en charge la communication bidirectionnelle en temps réel entre les clients et les serveurs. Faisant partie de HTML5, WebSocket rend le développement de ce type d'applications beaucoup plus facile que les méthodes auparavant disponibles. La plupart des navigateurs modernes prennent en charge WebSocket, notamment Chrome, Firefox, Internet Explorer, Opera et Safari, et de plus en plus de frameworks d'applications serveur prennent désormais également en charge WebSocket.

Pour une utilisation en production en entreprise, où plusieurs serveurs WebSocket sont nécessaires pour les performances et la haute disponibilité, une couche d'équilibrage de charge qui comprend le protocole WebSocket est requise, et NGINX prend en charge WebSocket depuis la version 1.3 et peut agir comme un proxy inverse et équilibrer la charge des applications WebSocket. (Toutes les versions de NGINX Plus prennent également en charge WebSocket.)

Consultez les tests de performances récents sur l’évolutivité de NGINX pour équilibrer la charge des connexions WebSocket.

Le protocole WebSocket est différent du protocole HTTP, mais la négociation WebSocket est compatible avec HTTP, en utilisant la fonction de mise à niveau HTTP pour mettre à niveau la connexion de HTTP vers WebSocket. Cela permet aux applications WebSocket de s'intégrer plus facilement dans les infrastructures existantes. Par exemple, les applications WebSocket peuvent utiliser les ports HTTP standard 80 et 443, permettant ainsi l’utilisation de règles de pare-feu existantes.

Une application WebSocket maintient une connexion longue durée ouverte entre le client et le serveur, facilitant ainsi le développement d’applications en temps réel. Le mécanisme de mise à niveau HTTP utilisé pour mettre à niveau la connexion de HTTP vers WebSocket utilise les en-têtes Upgrade et Connection . Un serveur proxy inverse est confronté à certains défis lors de la prise en charge de WebSocket. L’une d’entre elles est que WebSocket est un protocole hop-by-hop, donc lorsqu’un serveur proxy intercepte une demande de mise à niveau d’un client, il doit envoyer sa propre demande de mise à niveau au serveur principal, y compris les en-têtes appropriés. De plus, comme les connexions WebSocket ont une longue durée de vie, contrairement aux connexions de courte durée typiques utilisées par HTTP, le proxy inverse doit permettre à ces connexions de rester ouvertes, plutôt que de les fermer parce qu’elles semblent inactives.

NGINX prend en charge WebSocket en permettant la configuration d'un tunnel entre un client et un serveur backend. Pour que NGINX envoie la demande de mise à niveau du client au serveur principal, les en-têtes Upgrade et Connection doivent être définis explicitement, comme dans cet exemple :

emplacement /wsapp/ { proxy_pass http://wsbackend;
proxy_http_version 1.1;
proxy_set_header Mise à niveau $http_upgrade;
proxy_set_header Connexion "Mise à niveau";
proxy_set_header Hôte $host;
}

Une fois cela fait, NGINX traite cela comme une connexion WebSocket.

Exemple de WebSocket NGINX

Voici un exemple concret pour montrer que NGINX fonctionne comme un proxy WebSocket. Cet exemple utilise ws , une implémentation WebSocket basée sur Node.js . NGINX agit comme un proxy inverse pour une application WebSocket simple utilisant ws et Node.js. Ces instructions ont été testées avec Ubuntu 13.10 et CentOS 6.5 mais peuvent nécessiter d'être ajustées pour d'autres systèmes d'exploitation et versions. Pour cet exemple, l'adresse IP du serveur WebSocket est 192.168.100.10 et l'adresse IP du serveur NGINX est 192.168.100.20.

  1. Si vous n’avez pas encore installé Node.js et npm, exécutez la commande suivante :

    • Pour Debian et Ubuntu :

      $ sudo apt-get install nodejs npm
    • Pour RHEL et CentOS :

      $ sudo yum install nodejs npm
  2. Node.js est installé en tant que nodejs sur Ubuntu et en tant que node sur CentOS. L'exemple utilise node , donc sur Ubuntu nous devons créer un lien symbolique de nodejs vers node :

    $ ln -s /usr/bin/nodejs /usr/local/bin/node
  3. Pour installer ws , exécutez la commande suivante :

    $ sudo npm install ws

    Note: Si vous recevez le message d'erreur : « Erreur : échec de récupération à partir du registre : ws », exécutez la commande suivante pour résoudre le problème :

    $ sudo npm config définir le registre http://registry.npmjs.org/

    Exécutez ensuite à nouveau la commande sudo npm install ws .

  4. ws est livré avec le programme /root/node_modules/ws/bin/wscat que nous utiliserons pour notre client, mais nous devons créer un programme pour agir en tant que serveur. Créez un fichier appelé server.js avec ce contenu :

    console.log("Serveur démarré");
    var Msg = '';
    var WebSocketServer = require('ws').Server
    , wss = new WebSocketServer({port: 8010});
    wss.on('connection', function(ws) {
    ws.on('message', function(message) {
    console.log('Reçu du client : %s', message);
    ws.send('Serveur reçu du client : ' + message);
    });
    });
  5. Pour exécuter le programme serveur, exécutez la commande suivante :
    $ node serveur.js
  6. Le serveur imprime un message initial « Serveur démarré » puis écoute sur le port 8010, en attendant qu'un client s'y connecte. Lorsqu'il reçoit une demande client, il la renvoie et renvoie un message au client contenant le message qu'il a reçu. Pour que NGINX proxy ces requêtes, nous créons la configuration suivante. Nous ajoutons le bloc de carte afin que l'en-tête de connexion soit correctement défini pour se fermer lorsque l'en-tête de mise à niveau dans la demande est défini sur '' .

    http {
    map $http_upgrade $connection_upgrade {
    default upgrade;
    '' close;
    }
    
    websocket en amont {
    server 192.168.100.10:8010;
    }
    
    server {
    listen 8020;
    location / {
    proxy_pass http://websocket;
    proxy_http_version 1.1;
    proxy_set_header Mise à niveau $http_upgrade;
    proxy_set_header Connexion $connection_upgrade;
    proxy_set_header Hôte $host;
    }
    }
    }

    NGINX écoute sur le port 8020 et transmet les requêtes au serveur WebSocket principal. Les directives proxy_set_header permettent à NGINX de gérer correctement le protocole WebSocket.

  7. Pour tester le serveur, nous exécutons wscat en tant que client :

    $ /root/node_modules/ws/bin/wscat --connect ws://192.168.100.20:8020

    wscat se connecte au serveur WebSocket via le proxy NGINX. Lorsque vous saisissez un message à envoyer par wscat au serveur, vous le voyez répercuté sur le serveur, puis un message du serveur apparaît sur le client. Voici un exemple d’interaction :

    Serveur: Client:
    $ node serveur.js
    Le serveur a démarré
     
     
     
     
     
    wscat --connect ws://192.168.100.20:8020
    Connecté (appuyez sur CTRL+C pour quitter)
    > Bonjour
    Reçu du client : Bonjour
    < Le serveur a reçu du client : Bonjour

    Ici, nous voyons que le client et le serveur peuvent communiquer via NGINX qui agit comme un proxy et les messages peuvent continuer à être envoyés dans les deux sens jusqu'à ce que le client ou le serveur se déconnecte. Pour que NGINX gère correctement WebSocket, il suffit de définir correctement les en-têtes pour gérer la demande de mise à niveau qui met à niveau la connexion de HTTP vers WebSocket.

Lectures complémentaires


« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."