SSE vs WebSocket: qual opção de tempo real usar | We.Inc
Server-sent events vs WebSockets: EventSource e WebSocket lado a lado, reconexão, dados binários, limites de conexão, um assistente de decisão e servidores Node mínimos para os dois.
Server-sent events enviam texto em stream do servidor para o navegador por uma resposta HTTP comum, e a API EventSource reconecta sozinha. Um WebSocket faz o upgrade da conexão para um canal bidirecional que leva texto ou binário nos dois sentidos. Use SSE para feeds, notificações e progresso; use WebSockets quando o navegador precisa enviar mensagens frequentes de volta.
Lado a lado
Recurso
Server-sent events
WebSocket
Direção
Só do servidor para o cliente
Nos dois sentidos ao mesmo tempo
API do navegador
EventSource
WebSocket
Protocolo
HTTP simples, text/event-stream
HTTP Upgrade, depois ws:// ou wss://
Dados
Só texto UTF-8
Texto ou binário
Reconexão
Automática, retoma com Last-Event-ID
Você mesmo escreve
Conexões abertas no HTTP/1
6 por navegador por domínio
Limites separados, definidos por cada navegador
Não sabe qual dos dois o seu recurso precisa? Marque no assistente abaixo as afirmações que valem para ele. Ele aplica as mesmas regras da tabela acima e diz qual API se encaixa e por quê.
Marque cada afirmação que descreve o seu recurso.
Leia a recomendação e o motivo que ela apresenta.
Copie o código de cliente e de servidor correspondente nas seções mais abaixo.
Troque a URL e os nomes de evento pelos seus e rode o servidor com Node.
Envie uma linha de comentário, dois-pontos seguidos de texto, a cada 15 a 30 segundos em um stream SSE para que proxies ociosos não o cortem.
Dê um id a cada evento SSE. Quando o navegador reconecta, ele devolve esse valor no cabeçalho Last-Event-ID, e o seu servidor pode reenviar o que ficou para trás.
Sirva SSE por HTTP/2 sempre que puder, já que o limite de seis conexões do HTTP/1 é compartilhado por todas as abas abertas no seu site.
Com WebSockets, observe bufferedAmount antes de enviar rajadas grandes; a API em si não tem backpressure.
Perguntas frequentes
O navegador consegue enviar dados ao servidor com SSE?
Não pelo próprio stream. O stream de eventos só flui do servidor para o cliente, então o navegador envia as mensagens dele com requisições fetch comuns. Para tráfego em estilo de chat nos dois sentidos, um WebSocket se encaixa melhor.
Como faço o EventSource parar de reconectar?
Chame close() no cliente. Do lado do servidor, o padrão HTML diz que uma resposta 204 No Content indica ao cliente que pare de reconectar.
Posso enviar um cabeçalho Authorization com EventSource?
Não. O construtor recebe só uma URL e um objeto de opções cuja única configuração é withCredentials. Use um cookie, um token de curta duração na URL ou um leitor baseado em fetch se precisar de cabeçalhos personalizados.
SSE ficou ultrapassado agora que existem WebSockets?
Não. O formato text/event-stream continua sendo uma boa escolha para feeds de mão única porque passa por servidores HTTP, proxies e autenticação normais sem troca de protocolo.
Qual dos dois usa menos recursos do servidor?
Os dois mantêm uma conexão de longa duração por cliente, então a diferença é pequena. O que importa mais é se a sua hospedagem permite respostas de longa duração ou upgrades de protocolo, então confira primeiro os limites de duração de requisição dela.
Como os server-sent events funcionam
O servidor responde a um GET normal com Content-Type text/event-stream e mantém a resposta aberta. Cada mensagem tem algumas linhas como event:, data: e id:, terminadas por uma linha em branco. Várias linhas data: em uma mensagem são unidas com quebras de linha.
O EventSource do navegador interpreta esse stream, dispara um evento message para mensagens sem nome e um evento nomeado para as demais, e reconecta sozinho depois de uma queda. Uma linha retry: define a espera, em milissegundos, antes de tentar de novo.
Como os WebSockets funcionam
O cliente começa com uma requisição HTTP que leva um cabeçalho Upgrade, e o servidor responde 101 Switching Protocols. A partir daí a conexão leva frames WebSocket, não HTTP, e qualquer um dos lados pode enviar a qualquer momento.
Essa liberdade tem um custo. Você escreve a própria lógica de reconexão, o próprio formato de mensagem, muitas vezes JSON com um campo type, e o próprio heartbeat. Um proxy que não repassa o cabeçalho Upgrade também derruba a conexão antes de ela começar.
Uma regra rápida
Se o navegador mais escuta do que fala, escolha SSE. Placares ao vivo, logs de build, status de pedidos, notificações e texto em stream se encaixam aqui.
Se o navegador fala tanto quanto escuta, ou se os dados são binários, escolha um WebSocket. Jogos multiplayer, editores colaborativos e salas de chat se encaixam aí.
Server-sent events: código mínimo
Servidor SSE em Node puro
Nenhuma biblioteca é necessária. A resposta fica aberta; cada write é um evento, e a linha de comentário impede que proxies ociosos a fechem.
EventSource no navegador
addEventListener usa o nome do evento vindo do stream. A reconexão acontece sem nenhum código seu.
WebSocket: código mínimo
Servidor WebSocket com o pacote ws
Instale com npm install ws. Ele devolve cada mensagem em maiúsculas para o cliente que a enviou.
WebSocket no navegador, com uma reconexão simples
Diferente do EventSource, nada reconecta por você, então este código espera um instante depois do close e abre um novo socket.
O navegador envia muitas mensagens de volta, várias por segundo ou mais
Os dados são binários, como trechos de áudio ou buffers de estado de jogo
Os clientes precisam recuperar eventos perdidos depois de uma queda de conexão
O tráfego passa por proxies ou hospedagens que só lidam com HTTP simples
Server-sent events se encaixam. Nada do que você marcou exige um canal bidirecional, e o EventSource dá reconexão e retomada de graça.
Um WebSocket se encaixa. Você precisa de mensagens frequentes do navegador ou de dados binários, que um stream de eventos não consegue levar.