node.js - rooms - Socket.io Websockets en un equilibrador de carga elástico de Amazon configurado por TCP
socket.io chat rooms example (4)
Ahora puede usar el nuevo equilibrador de carga de aplicaciones que AWS lanzó recientemente.
Simplemente reemplace el ELB (ahora llamado equilibrador de carga clásico) con el ALB (equilibrador de carga de la aplicación) y habilite las sesiones adhesivas.
ALB soporta sockets web. Esto debería funcionar.
https://aws.amazon.com/blogs/aws/new-aws-application-load-balancer/
http://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html
Estoy planeando configurar un grupo de servidores de aplicaciones NodeJS que ejecuten Socket.io en EC2, y me gustaría usar Elastic Load Balancer para distribuir la carga entre ellos. Sé que ELB no admite Websockets fuera de la caja, pero puedo usar la configuración que se describe aquí en el Escenario 2 .
Sin embargo, como se describe en la publicación del blog , observo que esta configuración no ofrece afinidad de sesión o información de IP de origen:
No podemos tener encabezados de Afinidad de sesión ni X-Forward con esta configuración porque ELB no está analizando los mensajes HTTP, por lo que es imposible hacer coincidir las cookies para asegurar la Afinidad de sesión ni inyectar encabezados X-Forward especiales.
¿Socket.io seguirá funcionando en estas circunstancias? ¿O hay otra forma de tener un conjunto de servidores de aplicaciones Socket.io detrás de un equilibrador de carga con SSL?
EDIT: Tim Caswell habla de hacer esto ya here . ¿Hay alguna publicación explicando cómo configurar esto? Una vez más, no hay una sesión fija aquí, pero las cosas parecen estar funcionando bien.
Como un lado, ¿son realmente necesarias las sesiones adhesivas con websockets? ¿La información viaja como solicitudes nuevas y separadas o hay una sola solicitud + conexión con la que se mueve toda la información?
Como mencioné en la publicación, solo usamos ELB para terminar SSL y equilibrar la carga en un clúster de servidores http-proxy que admiten websockets. ELB no habla directamente con los servidores websocket. El clúster de proxy HTTP maneja la búsqueda del servidor socket.io correcto para conectarse y garantizar la adherencia de la sesión.
Cuando ejecuta un servidor en una nube que tiene un equilibrador de carga / proxy inverso, enrutadores, etc., debe configurarlo para que funcione correctamente, especialmente cuando escala el servidor para usar varias instancias.
Una de las restricciones que tienen Socket.io, SockJS y bibliotecas similares es que necesitan hablar continuamente con la misma instancia del servidor. Funcionan perfectamente bien cuando solo hay 1 instancia del servidor.
Cuando escala su aplicación en un entorno de nube, el equilibrador de carga (Nginx en el caso de Cloud Foundry) tomará el control, y las solicitudes se enviarán a diferentes instancias, lo que causará que Socket.io se rompa.
Para ayudar en tales situaciones, los equilibradores de carga tienen una función llamada ''afinidades de sesión'' también conocida como ''afinidad de sesión''. La idea principal es que si se establece esta propiedad, luego de la primera solicitud de carga equilibrada, todas las siguientes solicitudes irán a la misma instancia del servidor.
En Cloud Foundry, las sesiones adhesivas basadas en cookies están habilitadas para aplicaciones que configuran la cookie jsessionid.
Nota: jsessionid es el nombre de la cookie comúnmente usado para rastrear sesiones en aplicaciones Java / Spring. Cloud Foundry simplemente está adoptando eso como la cookie de sesión fija para todos los marcos.
Por lo tanto, todo lo que deben hacer las aplicaciones es configurar una cookie con el nombre jsessionid para que funcione socket.io.
app.use (cookieParser); app.use (express.session ({store: sessionStore, clave: ''jsessionid'', secreto: ''su secreto aquí''}));
Así que estos son los pasos:
Express establece una cookie de sesión con el nombre jsessionid. Cuando socket.io se conecta, usa la misma cookie y golpea el equilibrador de carga. El equilibrador de carga siempre lo enruta al mismo servidor en el que se configuró la cookie. Si está utilizando el equilibrador de carga de aplicaciones, la configuración de la sesión se encuentra en el nivel del grupo objetivo.
Socket.io no funciona de manera inmediata, incluso con un TCP ELB porque realiza dos solicitudes HTTP antes de actualizar la conexión a websockets.
La primera conexión se utiliza para establecer el protocolo, ya que socket.io admite más que solo websockets.
GET /socket.io/1/?t=1360136617252 HTTP/1.1
User-Agent: node-XMLHttpRequest
Accept: */*
Host: localhost:9999
Connection: keep-alive
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Wed, 06 Feb 2013 07:43:37 GMT
Connection: keep-alive
Transfer-Encoding: chunked
47
xX_HbcG1DN_nufWddblv:60:60:websocket,htmlfile,xhr-polling,jsonp-polling
0
La segunda solicitud se utiliza para actualizar realmente la conexión:
GET /socket.io/1/websocket/xX_HbcG1DN_nufWddblv HTTP/1.1
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: MTMtMTM2MDEzNjYxNzMxOA==
Host: localhost:9999
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 249I3zzVp0SzEn0Te2RLp0iS/z0=
Puede ver en el ejemplo anterior que xX_HbcG1DN_nufWddblv
es una clave compartida entre solicitudes. Este es el problema. Los ELB realizan enrutamiento round-robin, lo que significa que la solicitud de actualización llega a un servidor que no participó en la negociación inicial. Como tal, el servidor no tiene idea de quién es el cliente.
Los datos de estado en memoria son el enemigo del balanceo de carga. Afortunadamente, socket.io admite el uso de Redis para almacenar los datos en su lugar. Si comparte su conexión redis con múltiples servidores, ellos esencialmente comparten las sesiones de todos los clientes.
Consulte la página wiki socket.io para obtener detalles sobre la configuración de Redis.