Balanceamento de carga web sockets

104

Tenho uma pergunta sobre como balancear a carga dos soquetes da web.

Tenho um servidor que suporta sockets web. Os navegadores se conectam ao meu site e cada um abre um portal para www.mydomain.com. Dessa forma, meu aplicativo de rede social pode enviar mensagens para os clientes.

Tradicionalmente, usando apenas solicitações HTTP, eu aumentaria a escala adicionando um segundo servidor e um balanceador de carga na frente dos dois servidores da web.

Com os soquetes da web, a conexão deve ser diretamente com o servidor da web, não com os balanceadores de carga, porque se uma máquina tem um limite físico de, digamos, 64k portas abertas e os clientes estão se conectando ao balanceador de carga, então não posso suportar mais de 64 mil usuários simultâneos.

Então, como eu -

  1. fazer com que o cliente se conecte diretamente ao servidor da web (em vez do balanceador de carga) quando a página for carregada? Devo simplesmente carregar o JavaScript de um nó e os balanceadores de carga (ou qualquer outro) modificam aleatoriamente a URL do script, sempre que a página é solicitada inicialmente?

  2. lidar com um início ondulante? O navegador notará que a conexão é encerrada quando o servidor da web é encerrado. Posso escrever código JavaScript para tentar reabrir a conexão, mas o nó ficará ausente por um tempo. Então, acho que teria que voltar ao balanceador de carga para consultar o endereço do próximo nó a ser usado.

  3. Eu me perguntei sobre os balanceadores de carga enviando um redirecionamento na solicitação inicial, para que o navegador inicialmente solicite www.mydomain.come seja redirecionado para www34.mydomain.com. Isso funciona muito bem, até o nó cair - e sites como o Facebook não fazem isso. Como eles fazem isso?

John smith
fonte
1
Você poderia balancear a carga na camada de rede, conforme sugerido aqui
Chris Snow,
1
Existem também abordagens alternativas como balanceamento de carga baseado em DNS ou usando um servidor de orquestração baseado em http. Tentei resumir as vantagens e desvantagens de cada abordagem em deepstream.io/blog/load-balancing-websocket-connections
wolframhempel
@wolframhempel Link está morto. :-(
Emile Cormier

Respostas:

94

Coloque um balanceador de carga L3 que distribua pacotes IP com base no hash de porta IP de origem para o farm de servidores WebSocket. Uma vez que o balanceador L3 não mantém nenhum estado (usando a porta IP de origem com hash), ele será dimensionado para a velocidade do fio em hardware de baixo custo (digamos 10 GbE). Como a distribuição é determinística (usando porta-IP de origem com hash), ela funcionará com TCP (e, portanto, com WebSocket).

Observe também que um limite rígido de 64k se aplica apenas ao TCP / IP de saída para um determinado endereço IP (de origem). Não se aplica ao TCP / IP de entrada. Testamos o Autobahn (um servidor WebSocket de alto desempenho) com 200k conexões ativas em uma VM de 2 núcleos e 4 GB de RAM.

Observe também que você pode fazer o balanceamento de carga L7 no caminho HTTP anunciado durante o handshake inicial do WebSocket. Nesse caso, o balanceador de carga deve manter o estado (qual par de porta IP de origem está indo para qual nó de back-end). Provavelmente será escalado para milhões de conexões, no entanto, em uma configuração decente.

Disclaimer: Sou o autor original da Autobahn e trabalho para o Tavendo.

oberstet
fonte
Então, eu carregaria minha biblioteca javascript a partir da URL do balanceador de carga e forneceria a URL do balanceador de carga quando crio o soquete da web em javascript - quer dizer que é transparente para o navegador? Isso é legal!
John Smith
1
Sim, há apenas 1 URL, e o nome do host do último deve resolver para seu balanceador de carga. O servidor backend WebSocket possui IPs internos (não públicos) e, opcionalmente, também pode ser executado em portas diferentes da pública. A única ressalva é que você pode precisar dizer aos servidores WebSocket qual é seu nome de host visível público, IP, porta, uma vez que os servidores WebSocket em conformidade verificarão se a URL fornecida no cabeçalho HTTP do handshake WS se ajusta ao nome de host / ip / porta que eles estão ouvindo.
oberstet
Não tenho muitas conexões de websocket para balancear, mas tenho muito tráfego em uma ou, digamos, muito poucas conexões. para simplificar, digamos uma conexão agora, como posso equilibrar as solicitações que passam por uma conexão de soquete da web?
user1870400
Quando eu faço mais conexões 5000+ no java websocket, ele não libera memória .... existe alguma solução?
Poonam Patel
3

Observe que, se a lógica do servidor websocket for executada em nodejs com socket.io, você pode dizer a socket.io para usar um armazenamento de chave / valor redis compartilhado para sincronização. Dessa forma, você nem mesmo precisa se preocupar com o balanceador de carga, os eventos se propagam entre as instâncias do servidor.

var io = require('socket.io')(3000);
var redis = require('socket.io-redis'); 
io.adapter(redis({ host: 'localhost', port: 6379 }));

Veja: http://socket.io/docs/using-multiple-nodes/

Mas, em algum momento, acho que redis pode se tornar o gargalo ...

Convolver
fonte
2

Você também pode obter balanceamento de carga da camada 7 com inspeção e "funcionalidade de roteamento"

Consulte "Como inspecionar e balancear a carga do tráfego de WebSockets usando Stingray Traffic Manager e, quando necessário, como gerenciar WebSockets e tráfego HTTP que é recebido no mesmo endereço IP e porta." https://splash.riverbed.com/docs/DOC-1451

David
fonte
2
Tive que fazer algumas investigações para encontrar as informações que você vinculou. A máquina de retorno me ajudou a localizar uma cópia ativa desse artigo: community.pulsesecure.net/t5/Pulse-Secure-vADC/…
Wyck