34 pontos por GN⁺ 2024-12-26 | 5 comentários | Compartilhar no WhatsApp

Server-Sent Events (SSE) são subestimados

  • A maioria dos desenvolvedores conhece WebSockets, mas SSE é uma alternativa mais simples e muitas vezes ignorada.
  • SSE estabelece um canal de comunicação unidirecional do servidor para o cliente por HTTP.
  • Ao contrário da conexão bidirecional dos WebSockets, SSE mantém uma conexão HTTP aberta para atualizações do servidor para o cliente.

Por que SSE é subestimado

  • Popularidade do WebSocket: o recurso de comunicação full-duplex dos WebSockets ofusca a abordagem mais simples do SSE.
  • Percepção sobre limitações: sua natureza unidirecional pode parecer limitante, mas é suficiente para muitos casos de uso.

Principais pontos fortes do SSE

  1. Simplicidade de implementação

    • Aproveita o protocolo HTTP padrão, eliminando a complexidade de gerenciar conexões WebSocket.
  2. Compatibilidade com infraestrutura

    • Funciona perfeitamente com a infraestrutura HTTP existente:
      • balanceadores de carga
      • proxies
      • firewalls
      • servidores HTTP padrão
  3. Eficiência no uso de recursos

    • Menor consumo de recursos em comparação com WebSockets:
      • natureza unidirecional
      • uso de conexões HTTP padrão
      • sem necessidade de manutenção contínua de sockets
  4. Reconexão automática

    • Suporte nativo do navegador:
      • tratamento de interrupções de conexão
      • tentativas automáticas de reconexão
      • experiência em tempo real mais resiliente
  5. Semântica clara

    • O padrão de comunicação unidirecional garante:
      • separação clara de responsabilidades
      • fluxo de dados intuitivo
      • lógica de aplicação simplificada

Aplicações práticas

  • feeds de notícias em tempo real e atualizações sociais
  • cotações de ações e dados financeiros
  • barras de progresso e monitoramento de tarefas
  • streaming de logs do servidor
  • edição colaborativa (para atualizações)
  • rankings de jogos
  • sistemas de rastreamento de localização

Exemplo de implementação

Lado do servidor (Flask)
  • A rota /stream lida com a conexão SSE.
  • generate_random_data() gera continuamente eventos formatados.
  • O tipo MIME text/event-stream sinaliza o protocolo SSE.
  • stream_with_context mantém o contexto da aplicação Flask.
Lado do cliente (JavaScript)
  • O objeto EventSource gerencia a conexão SSE.
  • O handler onmessage processa os eventos recebidos.
  • onerror lida com problemas de conexão.
  • O navegador cuida da reconexão automática.

Limitações e considerações

  1. Comunicação unidirecional

    • Possível apenas do servidor para o cliente
    • A comunicação do cliente para o servidor exige requisições HTTP separadas
  2. Suporte de navegadores

    • Bem suportado em navegadores modernos
    • Navegadores antigos podem exigir polyfill
  3. Formato dos dados

    • Suporta principalmente dados baseados em texto
    • Dados binários exigem codificação (ex.: Base64)

Boas práticas

  • Tratamento de erros

    • Trate erros de conexão com eventSource.onerror.
  • Gerenciamento de conexão

    • Encerre e limpe a conexão quando concluir.
  • Estratégia de reconexão

    • Defina um número máximo de tentativas e implemente a lógica de reconexão.

Exemplo real: implementação do ChatGPT

  • Modelos modernos de linguagem de grande porte (LLM) usam SSE para fornecer respostas em streaming.
  • Principais padrões:
    • retorno do cabeçalho content-type: text/event-stream
    • streaming de blocos de dados separados por \r\n\r\n

Conclusão

  • SSE oferece uma solução elegante para comunicação em tempo real entre servidor e cliente.
  • Sua simplicidade, eficiência e integração com a infraestrutura existente fazem dele uma escolha adequada para muitas aplicações.
  • WebSockets continuam úteis para comunicação bidirecional, mas SSE oferece uma solução mais focada e apropriada para cenários de streaming de dados unidirecional.

5 comentários

 
eususu 2024-12-27

Implementei a OpenAI via REST e usei SSE na prática.
Pretendo adotá-lo sempre que houver necessidade de comunicação unidirecional.

 
galadbran 2024-12-27

No caso de SSE, ele costuma não ser bloqueado por equipamentos de segurança (como WAF ou segurança inteligente), mas com frequência encontro casos em que o streaming por quebras de linha não funciona. (On-premises) É como se, no meio do caminho, recebessem toda a resposta primeiro e depois a enviassem de uma vez só.

 
savvykang 2024-12-27

É realmente uma pena que o OpenAPI não ofereça suporte a SSE

 
alska1039 2024-12-26

É realmente uma ótima forma de implementar comunicação bidirecional em um ambiente NAT.

 
GN⁺ 2024-12-26
Comentários do Hacker News
  • Mercure é um protocolo aberto baseado em SSE, usado como alternativa a soluções baseadas em WebSockets. O Mercure funciona em torno de um hub independente que mantém conexões SSE persistentes com os clientes e fornece uma API HTTP simples que pode ser usada por aplicativos de servidor e clientes. O Mercure adiciona recursos como mecanismo de autenticação baseado em JWT, assinatura de vários tópicos em uma única conexão, histórico de eventos e ajuste automático de estado quando ocorrem problemas de rede

  • A grande desvantagem do SSE é o limite no número máximo de conexões quando não se usa HTTP/2. Isso pode ser um problema ao abrir várias abas, já que o limite por navegador pode ser baixo

  • No CLI da Doppler, usaram SSE para implementar uma função de reinicialização automática. Os eventos são recebidos do servidor via SSE, as informações mais recentes de segredos são buscadas e então injetadas no processo da aplicação. O motivo para escolher SSE em vez de WebSockets foi evitar adicionar dependências extras à aplicação em Golang. Para resolver problemas de timeout HTTP, foi necessário enviar eventos de "ping" de forma intermitente

  • A natureza unidirecional do SSE pode parecer limitante, mas em muitos casos é suficiente. As principais limitações do SSE são ser apenas para texto e a limitação de conexões do navegador em HTTP/1.1. Ao usar HTTP/2 ou superior, o limite de conexões deixa de ser um problema. Quando desempenho é importante, pode-se optar por uma solução mais flexível e com menos overhead usando fetch e ReadableStream

  • Por causa da simplicidade do SSE, muitos desenvolvedores acabam não usando uma implementação adequada e fazem o parsing dos chunks de dados com expressões regulares. Isso pode causar problemas porque o SSE oferece suporte a comentários no stream

  • Data-star.dev é uma biblioteca frontend focada em fazer streaming de respostas de hipermídia via SSE. Foi desenvolvida usando Go e NATS como tecnologias de backend e é compatível com todas as implementações de SSE

  • SSE não é subestimado. Na verdade, está sendo usado pela Open AI para streaming de conclusões. Implementar SSE em uma base de código ReactJS foi difícil, e na época o Axios não dava suporte, então foi preciso usar o fetch nativo

  • Quando implementaram SSE em um projeto web, ao abrir mais de 6 abas o site parava de funcionar. O Firefox conta as conexões SSE dentro do limite máximo de 6 conexões por host, e isso bloqueia requisições adicionais

  • SSE é subestimado quando funciona bem. Em um projeto em andamento, estão enfrentando dificuldades com problemas de autenticação e de keep-alive em túneis. Isso não é um problema do protocolo, mas encontrar a solução tem sido difícil