WebSocket no Node.js: servidor, cliente, heartbeat e reconexão

WebSocket no Node.js: servidor ws, cliente nativo, heartbeat | We.Inc

Crie um servidor WebSocket no Node.js com o pacote ws, conecte com o cliente WebSocket nativo do Node, detecte sockets mortos com ping e pong e reconecte com backoff.

O Node.js não tem um servidor WebSocket nativo, então a maioria dos projetos instala o pacote ws e cria um WebSocketServer. Para o lado do cliente, o Node traz um WebSocket global compatível com o do navegador, adicionado na v21.0.0 e na v20.10.0, liberado sem flag na v22.0.0 e marcado como estável na v22.4.0. Adicione um heartbeat com ping e pong e reconexão com backoff antes de ir para produção.

Qual peça faz o quê

Este guia monta um pequeno servidor no estilo chat e os clientes que conversam com ele, nesta ordem: um servidor que ecoa e transmite mensagens, um script Node que conecta sem nenhuma dependência, um heartbeat que descarta conexões que morreram em silêncio e um cliente que volta depois que o servidor reinicia. A calculadora abaixo mostra como os atrasos entre tentativas crescem antes de você colocá-los no código.

Perguntas frequentes

O Node.js tem WebSocket nativo?

Só o cliente. A classe global WebSocket apareceu na v21.0.0 e na v20.10.0 atrás da flag --experimental-websocket, perdeu a flag na v22.0.0 e deixou de ser experimental na v22.4.0. Ainda não existe um servidor nativo, e por isso o ws continua sendo a escolha usual.

Devo usar ws ou Socket.IO?

O ws fala o protocolo WebSocket puro, então qualquer cliente padrão, incluindo o navegador e o global do Node, consegue conectar. O Socket.IO adiciona o próprio protocolo por cima, com salas e reconexão automática, mas exige a própria biblioteca de cliente do outro lado.

Por que conexões morrem sem um evento close?

Se um caminho de rede desaparece, como quando a tampa de um notebook é fechada, nenhum frame de close é enviado e o servidor mantém um socket meio aberto. O heartbeat encontra esses casos: um socket que não respondeu ao último ping é encerrado na rodada seguinte.

Um cliente no navegador pode enviar pings?

Não. A API do navegador só tem send() e close(). Os navegadores respondem sozinhos aos pings do servidor com pongs, e por isso o heartbeat do lado do servidor também funciona com clientes no navegador.

Como compartilho uma porta com um servidor HTTP?

Crie o servidor HTTP você mesmo, por exemplo com Express ou node:http, e passe-o como new WebSocketServer({ server }). Requisições de upgrade vão para o ws e requisições normais vão para a sua aplicação.

Como uma conexão começa

Heartbeats em palavras simples

Reconectar sem martelar o servidor

Passo 1: um servidor com ws

server.js: eco e broadcast

Cada mensagem é reenviada para todos os clientes abertos. O listener de error impede que um socket com problema derrube o processo.

Passo 2: um cliente sem dependências

client.js: o WebSocket global do Node

Roda sem mudanças no Node 22 ou posterior e no console do navegador, porque os dois expõem a mesma classe WebSocket.

Passo 3: descarte conexões mortas com ping e pong

Nossa versão do padrão do README do ws: marca como vivo no pong, encerra o que perdeu a última rodada.

Passo 4: um cliente que reconecta

reconnect.js: backoff exponencial com jitter

O atraso dobra a cada tentativa falha até um teto, recebe uma variação aleatória e zera quando uma conexão abre.

Atrás do nginx

O nginx só repassa o upgrade quando você mesmo encaminha os cabeçalhos Upgrade e Connection. Antes do nginx 1.29.7 você também precisa de proxy_http_version 1.1.

location do nginx para o socket

proxy_read_timeout aumenta o limite de inatividade de 60 segundos; o heartbeat acima mantém o tráfego fluindo de qualquer forma.

Calculadora de atraso de reconexão

Defina um primeiro atraso, um multiplicador e um teto para ver quanto tempo um cliente espera antes de cada nova tentativa, e a menor e a maior espera quando o jitter é adicionado.

Primeiro atraso (ms)

Multiplicador

Teto (ms)

Tentativas a mostrar

Adicionar jitter (esperar entre metade e o atraso inteiro)

Espera antes de cada tentativa de reconexão

Tentativa

Atraso

Com jitter

Total esperado até agora

{n} a {v} s

As mesmas configurações em código

Comece grátis · Sem cartão de crédito

Relacionados: Guias

Produto

Para quem é

Recursos

Recursos

Empresa

Mapa do site