Os WebSockets HTML mantêm uma conexão aberta para cada cliente? Isso escala?

159

Estou curioso para saber se alguém tem alguma informação sobre a escalabilidade do HTML WebSockets. Por tudo que li, parece que todo cliente manterá uma linha aberta de comunicação com o servidor. Só estou me perguntando como isso é dimensionado e quantas conexões abertas do WebSocket um servidor pode suportar. Talvez deixar essas conexões abertas não seja um problema na realidade, mas parece que é.

Ryan Montgomery
fonte
1
Não existe um HTML WebSocket. Você quer dizer HTTP WebSocket.
Marquês de Lorne

Respostas:

209

Em muitos aspectos, os WebSockets provavelmente terão uma escala melhor que as solicitações AJAX / HTML. No entanto, isso não significa que o WebSockets seja um substituto para todos os usos do AJAX / HTML.

Cada conexão TCP, por si só, consome muito pouco em termos de recursos do servidor. Muitas vezes, a configuração da conexão pode ser cara, mas manter uma conexão inativa é quase gratuita. A primeira limitação geralmente encontrada é o número máximo de descritores de arquivo (soquetes consomem descritores de arquivo) que podem ser abertos simultaneamente. Geralmente, o padrão é 1024, mas pode ser facilmente configurado mais alto.

Já tentou configurar um servidor da Web para suportar dezenas de milhares de clientes AJAX simultâneos? Mude esses clientes para clientes WebSockets e isso pode ser possível.

As conexões HTTP, embora não criem arquivos abertos ou consumam números de porta por um longo período, são mais caras em praticamente todas as outras formas:

  • Cada conexão HTTP carrega muita bagagem que não é usada na maioria das vezes: cookies, tipo de conteúdo, comprimento conetente, agente do usuário, ID do servidor, data, última modificação, etc. Depois que uma conexão WebSockets é estabelecida, somente o os dados exigidos pelo aplicativo precisam ser enviados e enviados.

  • Normalmente, os servidores HTTP são configurados para registrar o início e a conclusão de cada solicitação HTTP, ocupando o tempo do disco e da CPU. Tornar-se-á padrão registrar o início e a conclusão dos dados do WebSockets, mas enquanto a conexão dos WebSockets estiver realizando a transferência duplex, não haverá sobrecarga adicional de registro (exceto pelo aplicativo / serviço, se ele for projetado para isso).

  • Normalmente, aplicativos interativos que usam AJAX pesquisam continuamente ou usam algum tipo de mecanismo de pesquisa longa. O WebSockets é uma maneira muito mais limpa (e de recursos mais baixos) de fazer um modelo com mais eventos, em que o servidor e o cliente se notificam quando têm algo a relatar pela conexão existente.

  • A maioria dos servidores Web populares em produção possui um conjunto de processos (ou threads) para lidar com solicitações HTTP. À medida que a pressão aumenta, o tamanho do pool aumentará, pois cada processo / encadeamento lida com uma solicitação HTTP por vez. Cada processo / encadeamento adicional usa mais memória e a criação de novos processos / encadeamentos é um pouco mais caro do que criar novas conexões de soquete (o que esses processos / encadeamentos ainda precisam fazer). A maioria das estruturas populares de servidores WebSockets segue a rota do evento, que tende a escalar e ter melhor desempenho.

O principal benefício do WebSockets serão as conexões de menor latência para aplicativos interativos da Web. Ele será dimensionado melhor e consumirá menos recursos do servidor do que o HTTP AJAX / pesquisa longa (supondo que o aplicativo / servidor tenha sido projetado corretamente), mas a latência mais baixa da IMO é o principal benefício do WebSockets, pois permitirá novas classes de aplicativos da Web que não são possíveis com a sobrecarga atual e latência de AJAX / pesquisa longa.

Quando o padrão WebSockets se tornar mais finalizado e tiver um suporte mais amplo, fará sentido usá-lo para a maioria dos novos aplicativos interativos da Web que precisam se comunicar com frequência com o servidor. Para aplicativos da Web interativos existentes, isso realmente dependerá de quão bem o modelo atual de AJAX / pesquisa longa está funcionando. O esforço para converter será não trivial, portanto, em muitos casos, o custo não valerá o benefício.

Atualização :

Link útil: 600k conexões simultâneas de websocket na AWS usando o Node.js

kanaka
fonte
4
Anser impressionante. Obrigado por ter tempo para responder.
Ryan Montgomery
7
Ainda não sei como escalar uma vez que você bate na parede. É verdade que os WebSockets consomem menos recursos (eles escalam verticalmente), mas o HTTP é ótimo para escalar horizontalmente. Teoricamente, posso adicionar servidores à escala infinita. Sempre fiquei confuso sobre como escalar uma vez que você usa a capacidade de uma única caixa. Pensamentos?
Sean Clark Hess
6
@Sean. O WebSockets não é necessariamente pior na escala horizontal. Ele apenas abre novos aplicativos que não necessariamente aumentam com a mesma facilidade. Por exemplo, para servir dados estáticos, um monte de servidores WebSocket seria dimensionado tão bem (ou melhor) que um monte de servidores HTTP. É difícil escalar um jogo em tempo real de baixa latência, independentemente do transporte (e simplesmente não é realmente viável usando HTTP). A verdadeira questão é quão bem você dimensiona dados / aplicativos. Se que as escalas, em seguida, sua escolha de HTTP vs WebSockets deve ser baseada em outros fatores: latência, opções de implementação, suporte ao navegador, etc.
kanaka
2
Uma correção - uma conexão TCP consiste no IP de destino e na porta de destino. Isso significa que o limite de ± 64k portas é APENAS para um único cliente. Teoricamente, o servidor pode ter qualquer número de conexões abertas, limitadas SOMENTE pelo seu hardware.
Rizon
@Rizon, isso é verdade. Atualizei a resposta e alterei a limitação da porta aberta e mencionei a limitação do descritor de arquivo, que é a que as pessoas costumam encontrar primeiro.
Kanaka
36

Apenas um esclarecimento: o número de conexões do cliente que um servidor pode suportar não tem nada a ver com portas nesse cenário, pois o servidor [normalmente] está apenas ouvindo conexões WS / WSS em uma única porta. Eu acho que o que os outros comentadores pretendiam se referir eram descritores de arquivos. Você pode definir o número máximo de descritores de arquivo bastante alto, mas é necessário observar os tamanhos de buffer de soquete que se somam a cada soquete TCP / IP aberto. Aqui estão algumas informações adicionais: /server/48717/practical-maximum-open-file-descriptors-ulimit-n-for-a-high-volume-system

Quanto à latência reduzida via WS vs. HTTP, é verdade, pois não há mais análise de cabeçalhos HTTP além do handshake inicial do WS. Além disso, à medida que mais e mais pacotes são enviados com êxito, a janela de congestionamento do TCP aumenta, reduzindo efetivamente o RTT.

Michael
fonte
AFAIR existe uma porta de entrada, mas sempre uma porta de saída aberta para cada conexão. Isso é apenas uma parte do problema do C10k .
Arnaud Bouchez
14

Qualquer servidor único e moderno pode atender milhares de clientes de uma só vez . Seu software de servidor HTTP precisa ser orientado a IOCP (Event-Driven) (não estamos mais no Apache antigo, uma conexão = uma equação de thread / processo). Até o servidor HTTP incorporado no Windows (http.sys) é orientado para IOCP e muito eficiente (executando no modo kernel). Desse ponto de vista, não haverá muita diferença no dimensionamento entre o WebSockets e a conexão HTTP normal. Uma conexão TCP / IP usa pouco recurso (muito menos que um encadeamento) e o SO moderno é otimizado para lidar com muitas conexões simultâneas: WebSockets e HTTP são apenas protocolos da camada de aplicativo OSI 7, herdados dessas especificações TCP / IP.

Mas, por experiência, vi dois problemas principais com os WebSockets:

  1. Eles não suportam CDN;
  2. Eles têm possíveis problemas de segurança.

Então, eu recomendaria o seguinte, para qualquer projeto:

  • Use o WebSockets apenas para notificações de clientes (com um mecanismo de fallback para pesquisas longas - existem muitas bibliotecas por aí);
  • Use RESTful / JSON para todos os outros dados, usando uma CDN ou proxies para cache.

Na prática, os aplicativos WebSockets completos não se adaptam bem. Basta usar o WebSockets para o que eles foram projetados: notificações por push do servidor para o cliente.

Sobre os possíveis problemas do uso de WebSockets:

1. Considere usar uma CDN

Hoje (quase 4 anos depois), o dimensionamento da Web envolve o uso de front-ends da Content Delivery Network (CDN), não apenas para conteúdo estático (html, css, js), mas também para os dados do aplicativo (JSON) .

Obviamente, você não colocará todos os seus dados no cache da CDN, mas, na prática, muito conteúdo comum não será alterado com frequência. Suspeito que 80% dos seus recursos REST possam estar armazenados em cache ... Mesmo o tempo limite de expiração da CDN de um minuto (ou 30 segundos) pode ser suficiente para dar ao servidor central uma nova energia ao vivo e aprimorar muito a capacidade de resposta do aplicativo, pois a CDN pode ser ajustado geograficamente ...

Que eu saiba, ainda não há suporte para WebSockets na CDN e suspeito que nunca seria. Os WebSockets são válidos para o estado, enquanto o HTTP é sem estado, portanto, é muito facilmente armazenado em cache. De fato, para tornar o WebSockets compatível com CDN, pode ser necessário mudar para uma abordagem RESTful sem estado ... que não seria mais o WebSockets.

2. Questões de segurança

Os WebSockets têm possíveis problemas de segurança, especialmente sobre ataques do DOS. Para obter uma ilustração sobre as novas vulnerabilidades de segurança, consulte este conjunto de slides e este ticket de webkit .

Os WebSockets evitam qualquer chance de inspeção de pacotes no nível da camada de aplicativos OSI 7, que hoje em dia é bastante padrão em qualquer segurança comercial. De fato, o WebSockets torna a transmissão ofuscada, por isso pode ser uma grande violação do vazamento de segurança.

Arnaud Bouchez
fonte
2
@ArnaudBouchez - +1 para a boa exposição na CDN. Pergunta de acompanhamento rápido - o que você acha da viabilidade das redes de entrega de eventos? Modelado após CDNs, mas voltado para o fornecimento de dados de streaming, etc., em soquetes da Web ou em alguma outra tecnologia ainda não vista.
quixver
8

Pense desta maneira: o que é mais barato, mantendo uma conexão aberta ou abrindo uma nova conexão para cada solicitação (com a sobrecarga de negociação para isso, lembre-se de que é TCP).

É claro que depende da aplicação, mas para conexões em tempo real a longo prazo (por exemplo, um bate-papo AJAX), é muito melhor manter a conexão aberta.

O número máximo de conexões será limitado pelo número máximo de portas livres para os soquetes.

kaoD
fonte
Você pode manter a conexão aberta sem usar um WebSocket (graças à opção keep alive do HTTP / 1.1). Não sei se entendi seu ponto aqui.
Arnaud Bouchez
1
+1. As pessoas tendem a esquecer que a configuração de uma conexão TCP envolve um syn / ack / ack e o TLS requer mais viagens de ida e volta para a troca de chaves.
quixver
1
@ArnaudBouchez check en.wikipedia.org/wiki/HTTP_persistent_connection#HTTP_1.1 Os WebSockets ficam abertos pelo tempo que você deseja e não são hackeados (como pesquisas longas e outras alternativas).
KaoD 21/02
-5

Não, ele não escala, dá um tremendo trabalho aos comutadores de rotas intermediárias. Em seguida, no lado do servidor, as falhas de página (é necessário manter todos esses descritores) estão atingindo valores altos e o tempo para trazer um recurso para a área de trabalho aumenta. Estes são principalmente servidores escritos em JAVA e pode ser mais rápido manter esses gazilions de soquetes do que destruir / criar um. Quando você executa esse servidor em uma máquina, qualquer outro processo não pode mais se mover.

user2195463
fonte