NGINX como proxy de WebSocket

NGINX | 16 de mayo de 2014

El protocolo WebSocket permite crear aplicaciones web que admiten la comunicación bidireccional en tiempo real entre clientes y servidores. Como parte de HTML5, WebSocket facilita considerablemente el desarrollo de este tipo de aplicaciones en comparación con los métodos disponibles anteriormente. La mayoría de los navegadores modernos son compatibles con WebSocket, incluidos Chrome, Firefox, Internet Explorer, Opera y Safari, y cada vez más frameworks de aplicaciones de servidor también ofrecen compatibilidad con WebSocket.

Para su uso en entornos de producción empresariales, donde se necesitan varios servidores WebSocket para garantizar el rendimiento y la alta disponibilidad, se requiere una capa de balanceo de carga que comprenda el protocolo WebSocket. NGINX es compatible con WebSocket desde la versión 1.3 y puede actuar como proxy inverso y realizar el balanceo de carga de aplicaciones WebSocket. (Todas las versiones de NGINX Plus también son compatibles con WebSocket.)

Consulta las pruebas de rendimiento más recientes sobre la escalabilidad de NGINX para equilibrar la carga de las conexiones WebSocket.

El protocolo WebSocket es diferente del protocolo HTTP, pero el protocolo de enlace de WebSocket es compatible con HTTP, ya que utiliza el mecanismo Upgrade de HTTP para cambiar la conexión de HTTP a WebSocket. Esto permite integrar más fácilmente las aplicaciones WebSocket en las infraestructuras existentes. Por ejemplo, las aplicaciones WebSocket pueden utilizar los puertos HTTP estándar 80 y 443, lo que permite aprovechar las reglas de firewall existentes.

Una aplicación WebSocket mantiene abierta una conexión de larga duración entre el cliente y el servidor, lo que facilita el desarrollo de aplicaciones en tiempo real. El mecanismo HTTP Upgrade utilizado para cambiar la conexión de HTTP a WebSocket emplea las cabeceras Upgrade y Connection. Los servidores proxy inversos se enfrentan a algunos retos a la hora de admitir WebSocket. Uno de ellos es que WebSocket es un protocolo de salto a salto, por lo que, cuando un servidor proxy intercepta una solicitud Upgrade de un cliente, debe enviar su propia solicitud Upgrade al servidor backend, incluidas las cabeceras correspondientes. Además, dado que las conexiones WebSocket son de larga duración, a diferencia de las conexiones normalmente breves utilizadas por HTTP, el proxy inverso debe permitir que permanezcan abiertas en lugar de cerrarlas por parecer inactivas.

NGINX admite WebSocket al permitir establecer un túnel entre un cliente y un servidor backend. Para que NGINX envíe la solicitud de actualización del cliente al servidor backend, las cabeceras Upgrade y Connection deben configurarse explícitamente, como en este ejemplo:

location /wsapp/ {    proxy_pass http://wsbackend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header Host $host;
}

Una vez hecho esto, NGINX trata la conexión como una conexión WebSocket.

Ejemplo de WebSocket con NGINX

A continuación se muestra un ejemplo práctico de NGINX funcionando como proxy WebSocket. Este ejemplo utiliza ws, una implementación de WebSocket desarrollada sobre Node.js. NGINX actúa como proxy inverso para una aplicación WebSocket sencilla que utiliza ws y Node.js. Estas instrucciones se han probado con Ubuntu 13.10 y CentOS 6.5, pero puede que sea necesario adaptarlas para otros sistemas operativos y versiones. En este ejemplo, la dirección IP del servidor WebSocket es 192.168.100.10 y la del servidor NGINX es 192.168.100.20.

  1. Si aún no tiene instalados Node.js y npm, ejecute el siguiente comando:
    • Para Debian y Ubuntu:
$ sudo apt-get install nodejs npm
  • Para RHEL y CentOS:
$ sudo yum install nodejs npm
  1. Node.js se instala como nodejs en Ubuntu y como node en CentOS. El ejemplo utiliza node, por lo que en Ubuntu debemos crear un enlace simbólico de nodejs a node:
$ ln -s /usr/bin/nodejs /usr/local/bin/node
  1. Para instalar ws, ejecuta el siguiente comando:
$ sudo npm install ws
  1. Nota: Si aparece el mensaje de error «Error: failed to fetch from registry: ws», ejecuta el siguiente comando para solucionar el problema:
$ sudo npm config set registry http://registry.npmjs.org/
  1. A continuación, vuelve a ejecutar el comando «sudo npm install ws».
  2. ws incluye el programa /root/node_modules/ws/bin/wscat que utilizaremos como cliente, pero necesitamos crear un programa que actúe como servidor. Cree un archivo llamado server.js con el siguiente contenido:
console.log("Server started");
var Msg = '';
var WebSocketServer = require('ws').Server
    , wss = new WebSocketServer({port: 8010});
    wss.on('connection', function(ws) {
        ws.on('message', function(message) {
        console.log('Received from client: %s', message);
        ws.send('Server received from client: ' + message);
    });
 });
  1. Para ejecutar el programa del servidor, ejecute el siguiente comando:
$ node server.js
  1. El servidor muestra un mensaje inicial "Server started" y, a continuación, escucha en el puerto 8010 a la espera de que un cliente se conecte. Cuando recibe una solicitud de un cliente, la reproduce y devuelve al cliente un mensaje que contiene el mensaje recibido. Para que NGINX actúe como proxy de estas solicitudes, creamos la siguiente configuración. Añadimos el bloque map para que el encabezado Connection se establezca correctamente en close cuando el encabezado Upgrade de la solicitud esté establecido en ''.
http {
    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }
 
    upstream websocket {
        server 192.168.100.10:8010;
    }
 
    server {
        listen 8020;
        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;
        }
    }
}
  1. NGINX escucha en el puerto 8020 y redirige las solicitudes al servidor WebSocket del backend. Las directivas proxy_set_header permiten que NGINX gestione correctamente el protocolo WebSocket.
  2. Para probar el servidor, ejecutamos wscat como cliente:
$ /root/node_modules/ws/bin/wscat --connect ws://192.168.100.20:8020
  1. wscat se conecta al servidor WebSocket a través del proxy NGINX. Cuando escribes un mensaje para que wscat lo envíe al servidor, ves cómo se muestra en el servidor y, a continuación, aparece en el cliente un mensaje procedente del servidor. Este es un ejemplo de interacción: Servidor: Cliente: $node server.js
    Servidor iniciado 
     

    wscat --connect ws://192.168.100.20:8020
    Conectado (pulsa CTRL+C para salir)
    > Hola
    Recibido del cliente: Hola < El servidor ha recibido del cliente: Hola Aquí vemos que el cliente y el servidor pueden comunicarse a través de NGINX, que actúa como proxy, y que los mensajes pueden seguir enviándose en ambos sentidos hasta que el cliente o el servidor se desconecten. Para que NGINX gestione correctamente WebSocket, basta con configurar adecuadamente las cabeceras para procesar la solicitud Upgrade, que cambia la conexión de HTTP a WebSocket.

Lecturas adicionales


Compartir
Etiquetas: Tech, F5 NGINX, 2014

Sobre el autor

Rick Nelson
Rick NelsonVicepresidente regional de Ingeniería de Soluciones

Más artículos de Rick Nelson

Artículos relacionados del blog

Únete a F5 NGINX en AppWorld 2024
NGINX | 04/01/2024

Únete a F5 NGINX en AppWorld 2024

Descubre las numerosas razones para asistir al evento insignia de F5, que incluirá un emocionante anuncio sobre la cartera de productos NGINX.

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source
NGINX | 26/09/2023

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source

La función de diccionario compartido permite configurar NGINX sin necesidad de reiniciarlo al renovar los certificados SSL/TLS.

Exposición de APIs en Kubernetes
NGINX | 10/03/2022

Exposición de APIs en Kubernetes

La unidad 2 de Microservices March 2022 se centra en cómo exponer tus API en Kubernetes. Aquí tienes enlaces a los recursos que necesitas: la retransmisión en directo del 14 de marzo, artículos de blog y otros recursos de preparación, y el laboratorio práctico «Protege las API de Kubernetes mediante la limitación de solicitudes».

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto
NGINX | 23/08/2021

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto

Hoy, en NGINX Sprint 2.0, anunciamos cómo respaldaremos nuestra visión del futuro de las aplicaciones modernas con una mayor presencia en la comunidad de código abierto, incluida la participación en el proyecto comunitario Kubernetes, nuevos proyectos de software de código abierto y la arquitectura de referencia para aplicaciones modernas.

Presentamos NGINX Plus R22
NGINX | 09/06/2020

Presentamos NGINX Plus R22

NGINX Plus R22 incorpora nuevas funcionalidades, como la compatibilidad con OCSP para verificar la revocación de certificados en TLS mutuo, el uso de varios proveedores de identidad OIDC en una configuración, el seguimiento en tiempo real de la limitación de solicitudes y conexiones en el panel de NGINX Plus y mejoras en NGINX JavaScript.

Presentamos NGINX Plus R17
NGINX | 11/12/2018

Presentamos NGINX Plus R17

NGINX Plus R17 incorpora compatibilidad con la limitación de velocidad en dos fases y con TLS 1.3, la versión más reciente del protocolo Transport Layer Security. La configuración de OpenID Connect es más sencilla y NGINX ModSecurity WAF es el doble de rápido que antes. También se ha actualizado el módulo JavaScript de NGINX.