Tengo una pregunta sobre cómo equilibrar la carga de los sockets web.
Tengo un servidor que admite sockets web. Los navegadores se conectan a mi sitio y cada uno abre una conexión web a www.mydomain.com
. De esa manera, mi aplicación de red social puede enviar mensajes a los clientes.
Tradicionalmente, usando solo solicitudes HTTP, escalaría agregando un segundo servidor y un equilibrador de carga frente a los dos servidores web.
Con los sockets web, la conexión tiene que ser directamente con el servidor web, no con los balanceadores de carga, porque si una máquina tiene un límite físico de, digamos, 64k puertos abiertos, y los clientes se conectan al balanceador de carga, entonces no puedo soportar más de 64.000 usuarios simultáneos.
Entonces, ¿cómo yo ...
conseguir que el cliente se conecte directamente al servidor web (en lugar del equilibrador de carga) cuando se carga la página? ¿Simplemente cargo JavaScript desde un nodo y los balanceadores de carga (o lo que sea) modifican aleatoriamente la URL del script cada vez que se solicita la página inicialmente?
manejar un comienzo de onda? El navegador notará que la conexión se cierra cuando el servidor web se apaga. Puedo escribir código JavaScript para intentar reabrir la conexión, pero el nodo desaparecerá por un tiempo. Entonces, supongo que tendría que volver al equilibrador de carga para consultar la dirección del siguiente nodo a usar.
Me pregunté si los balanceadores de carga envían una redirección en la solicitud inicial, de modo que el navegador inicialmente solicita
www.mydomain.com
y se redirige awww34.mydomain.com
. Eso funciona bastante bien, hasta que el nodo se cae, y sitios como Facebook no hacen eso. ¿Cómo lo hicieron?
fuente
Respuestas:
Coloque un equilibrador de carga L3 que distribuya paquetes IP basados en el hash del puerto IP de origen a su granja de servidores WebSocket. Dado que el equilibrador L3 no mantiene ningún estado (utilizando el puerto IP de origen con hash), escalará a la velocidad del cable en hardware de gama baja (por ejemplo, 10 GbE). Dado que la distribución es determinista (utilizando el puerto IP de origen con hash), funcionará con TCP (y, por lo tanto, WebSocket).
También tenga en cuenta que un límite estricto de 64k solo se aplica a TCP / IP saliente para una dirección IP determinada (de origen). No se aplica a TCP / IP entrante. Hemos probado Autobahn (un servidor WebSocket de alto rendimiento) con 200k conexiones activas en una máquina virtual de 2 núcleos y 4 GB de RAM.
También tenga en cuenta que puede realizar el equilibrio de carga L7 en la ruta HTTP anunciada durante el protocolo de enlace inicial de WebSocket. En ese caso, el equilibrador de carga tiene que mantener el estado (qué par de puerto IP de origen va a qué nodo de backend). Probablemente escalará a millones de conexiones, sin embargo, con una configuración decente.
Descargo de responsabilidad: soy el autor original de Autobahn y trabajo para Tavendo.
fuente
Tenga en cuenta que si la lógica de su servidor websocket se ejecuta en nodejs con socket.io, puede decirle a socket.io que use un almacén de claves / valores redis compartido para la sincronización. De esta manera, ni siquiera tiene que preocuparse por el equilibrador de carga, los eventos se propagarán entre las instancias del servidor.
Ver: http://socket.io/docs/using-multiple-nodes/
Pero en algún momento supongo que redis puede convertirse en el cuello de botella ...
fuente
También puede lograr el equilibrio de carga de capa 7 con inspección y "funcionalidad de enrutamiento"
Consulte "Cómo inspeccionar y equilibrar la carga del tráfico de WebSockets con Stingray Traffic Manager y, cuando sea necesario, cómo administrar el tráfico de WebSockets y HTTP que se recibe en la misma dirección IP y puerto". https://splash.riverbed.com/docs/DOC-1451
fuente