node.js - example - AWS application load balancecer y socket.io
socket io redis (1)
Tengo una sala de chat socket.io ejecutándose, cuyo tráfico se hace más grande ya que estamos corriendo en una máquina. Hemos ejecutado pruebas comparativas utilizando la biblioteca ws para tomas de corriente y funcionan mucho mejor, lo que haría un mejor uso de nuestro hardware. Sin embargo, esto tendría un costo de tener que reescribir nuestra aplicación.
Nuestra aplicación socket.io permite a los usuarios crear salas de chat privadas que se implementan mediante el uso de espacios de nombres. P.ej
localhost:8080/room/1
localhost:8080/room/2
localhost:8080/room/3
Cuando todo está en una instancia, es bastante fácil, pero ahora estamos buscando expandir esta capacidad en múltiples nodos.
Ejecutamos esta instancia en la nube de Amazon. Anteriormente parecía que escalar websockets era un problema con los ELB. Nos hemos dado cuenta de que Amazon ahora es compatible con el balanceador de carga de aplicaciones que admite websockets. Esto suena genial, pero después de leer la documentación debo admitir que realmente no sé lo que significa. Si estoy usando socket.io con miles de espacios de nombres, ¿simplemente pongo instancias detrás de este ALB y todo funcionará? Mis preguntas principales son:
Si x número de usuarios se une a un espacio de nombre, ¿el ALB redirigirá automáticamente mis mensajes hacia y desde los usuarios adecuados? Entonces digamos que tengo 5 instancias de socket.io vanilla detrás del ALB. El usuario 1 crea un espacio de nombre. Pasan unas horas y el usuario 99999 viene y quiere unirse a este espacio de nombres. ¿Habrá algún código adicional escrito para hacer esto o el alb redirigirá todo a donde debería ir? Lo mismo vale para enviar y recibir mensajes?
Si bien ALB equilibrará la carga de los usuarios correctamente, deberá adaptar su código un poco ya que los usuarios que se unieron a una habitación específica se dispersarán a través de diferentes servidores.
En su documentación, socket.io proporciona una forma de hacer esto:
Ahora que tiene múltiples nodos Socket.IO que aceptan conexiones, si desea transmitir eventos a todos (o incluso a todos en una determinada sala), necesitará alguna forma de pasar mensajes entre procesos o computadoras.
La interfaz a cargo de los mensajes de enrutamiento es lo que llamamos el Adaptador. Puede implementar su propio sobre el socket.io-adapter (heredando de él) o puede usar el que proporcionamos en la parte superior de Redis: socket.io-redis:
var io = require(''socket.io'')(3000);
var redis = require(''socket.io-redis'');
io.adapter(redis({ host: ''localhost'', port: 6379 }));
Configuración de ALB
Recomendaría habilitar la sesión adhesiva en su ALB; de lo contrario, el protocolo de enlace socket.io fallará cuando use un transporte que no sea de websocket, como un sondeo largo, ya que la tarea de intercambio de información que utiliza este transporte requiere más de una solicitud y necesita todas esas solicitudes para ser realizado contra el mismo servidor.
Alternativa usando enrutamiento ALB sin adaptador socket.io.
Si quisiera evitar tener una base de datos redis. Por ejemplo, si mis habitaciones son creadas por usuarios, si el usuario A crea una habitación en la instancia 4, si otro usuario desea unirse a esta sala, ¿cómo sabría en qué instancia está? ¿Necesitaría el adaptador aquí también?
El objetivo de esta alternativa es asignar cada sala a una Instancia EC2 específica. Vamos a lograr esto usando ALB Routing
N habitaciones> 1 instancia.
Paso 1:
Deberá cambiar la URL de su habitación a algo como:
/i1/room/550
/i1/room/20
/i2/room/5
/i5/room/492
siendo:
/{instance-number}/room/{room-id}
Esto es necesario para que ALB pueda enrutar cada habitación a una instancia específica.
Paso 2:
Crea N grupos objetivo (N es el número de instancias que tienes en este momento)
Paso 3:
Registre cada instancia para cada grupo objetivo
Grupos de destino> Grupo de destino de instancia X> pestaña Destino> Editar> Elegir instancia X> agregar a registrado
Target group X > EC2 Instance X
Target group Y > EC2 Instance Y
Etapa 4:
Editar reglas de objetivo ALB
Balanceadores de carga> Su ALB> Oyentes> Ver / Editar reglas
Paso 5:
Crea una regla por grupo / instancia objetivo con la siguiente configuración:
- IF> Ruta:
/iX/room/*
- ENTONCES> reenviar a:
instanceX
Una vez que tenga esta configuración cuando ingrese:
-
/i1/room/550
usará EC2 Instance 1. -
/i2/room/200
usará EC2 Instance 2
y así.
Ahora tendrá que hacer su propia lógica para que las habitaciones se equilibren en sus instancias. No desea tener una instancia alojando a casi todos los grupos.
Recomiendo el primer acercamiento ya que se puede escalar automáticamente.