34 puntos por GN⁺ 2024-12-26 | 5 comentarios | Compartir por WhatsApp

Los Server-Sent Events (SSE) están subestimados

  • La mayoría de los desarrolladores conocen WebSockets, pero SSE es una alternativa más simple y a menudo pasada por alto.
  • SSE establece un canal de comunicación unidireccional del servidor al cliente a través de HTTP.
  • A diferencia de la conexión bidireccional de WebSockets, SSE mantiene una conexión HTTP abierta para enviar actualizaciones del servidor al cliente.

Por qué SSE está subestimado

  • Popularidad de WebSocket: La capacidad de comunicación full-duplex de WebSockets eclipsa el enfoque más simple de SSE.
  • Percepción de sus limitaciones: Su naturaleza unidireccional puede parecer limitante, pero es suficiente para muchos casos de uso.

Principales fortalezas de SSE

  1. Simplicidad de implementación

    • Aprovecha el protocolo HTTP estándar y elimina la complejidad de gestionar conexiones WebSocket.
  2. Compatibilidad con la infraestructura

    • Funciona sin problemas con la infraestructura HTTP existente:
      • balanceadores de carga
      • proxies
      • firewalls
      • servidores HTTP estándar
  3. Eficiencia de recursos

    • Menor consumo de recursos en comparación con WebSockets:
      • naturaleza unidireccional
      • uso de conexiones HTTP estándar
      • no requiere mantenimiento constante del socket
  4. Reconexión automática

    • Soporte integrado en el navegador para:
      • manejo de desconexiones
      • intentos automáticos de reconexión
      • una experiencia en tiempo real resiliente
  5. Semántica clara

    • El patrón de comunicación unidireccional garantiza:
      • una separación clara de responsabilidades
      • un flujo de datos intuitivo
      • lógica de aplicación simplificada

Aplicaciones prácticas

  • feeds de noticias en tiempo real y actualizaciones sociales
  • cotizaciones bursátiles y datos financieros
  • barras de progreso y monitoreo de tareas
  • streaming de logs del servidor
  • edición colaborativa (para actualizaciones)
  • tablas de clasificación en juegos
  • sistemas de seguimiento de ubicación

Ejemplo de implementación

Lado del servidor (Flask)
  • La ruta /stream maneja la conexión SSE.
  • generate_random_data() genera continuamente eventos con el formato adecuado.
  • El tipo MIME text/event-stream indica el protocolo SSE.
  • stream_with_context mantiene el contexto de la aplicación Flask.
Lado del cliente (JavaScript)
  • El objeto EventSource gestiona la conexión SSE.
  • El handler onmessage procesa los eventos recibidos.
  • onerror maneja los problemas de conexión.
  • El navegador se encarga de la reconexión automática.

Limitaciones y consideraciones

  1. Comunicación unidireccional

    • Solo es posible del servidor al cliente
    • La comunicación del cliente al servidor requiere solicitudes HTTP separadas
  2. Soporte en navegadores

    • Tiene buen soporte en navegadores modernos
    • En navegadores antiguos puede requerir un polyfill
  3. Formato de datos

    • Principalmente soporta datos basados en texto
    • Los datos binarios requieren codificación (por ejemplo, Base64)

Mejores prácticas

  • Manejo de errores

    • Manejar los errores de conexión con eventSource.onerror.
  • Gestión de conexiones

    • Limpiar la conexión al finalizar.
  • Estrategia de reconexión

    • Establecer un número máximo de reintentos e implementar la lógica de reconexión.

Ejemplo real: implementación de ChatGPT

  • Los modelos modernos de lenguaje de gran escala (LLM) usan SSE para ofrecer respuestas en streaming.
  • Patrones principales:
    • devolver el header content-type: text/event-stream
    • hacer streaming de bloques de datos separados por \r\n\r\n

Conclusión

  • SSE ofrece una solución elegante para la comunicación en tiempo real entre servidor y cliente.
  • Su simplicidad, eficiencia e integración con la infraestructura existente lo convierten en una opción adecuada para muchas aplicaciones.
  • Aunque WebSockets sigue siendo útil para la comunicación bidireccional, SSE ofrece una solución más enfocada y apropiada para escenarios de streaming de datos unidireccional.

5 comentarios

 
eususu 2024-12-27

Implementé OpenAI con REST y realmente usé SSE.
Definitivamente pienso adoptarlo en situaciones donde se necesite comunicación unidireccional.

 
galadbran 2024-12-27

Con SSE, los equipos de seguridad (como firewalls web o seguridad inteligente) normalmente no lo bloquean, pero a menudo me encuentro con casos en los que el streaming por saltos de línea no funciona. Es como si en el medio (on-premises) recibieran toda la respuesta y luego la enviaran de una sola vez.

 
savvykang 2024-12-27

Es una verdadera lástima que OpenAPI no sea compatible con SSE.

 
alska1039 2024-12-26

Es una muy buena forma de establecer comunicación bidireccional en entornos NAT.

 
GN⁺ 2024-12-26
Opiniones de Hacker News
  • Mercure es un protocolo abierto basado en SSE que se usa como alternativa a soluciones basadas en WebSockets. Mercure funciona alrededor de un hub independiente que mantiene conexiones SSE persistentes con los clientes y ofrece una API HTTP simple que pueden usar tanto la app del servidor como los clientes. Mercure añade funciones como un mecanismo de autenticación basado en JWT, suscripción a múltiples temas con una sola conexión, historial de eventos y ajuste automático de estado cuando ocurren problemas de red

  • La gran desventaja de SSE es que, si no se usa HTTP/2, existe un límite en el número máximo de conexiones. Como el límite por navegador es bajo, esto puede causar problemas al abrir varias pestañas

  • En el CLI de Doppler usaron SSE para implementar la función de reinicio automático. A través de SSE reciben eventos del servidor, obtienen los secretos más recientes y los inyectan en el proceso de la aplicación. Eligieron SSE en lugar de WebSockets para no agregar dependencias adicionales a la aplicación en Golang. Para resolver problemas de timeout de HTTP, tuvieron que enviar eventos de "ping" de forma intermitente

  • La naturaleza unidireccional de SSE puede parecer limitante, pero en muchos casos es suficiente. Sus principales limitaciones son que solo maneja texto y el límite de conexiones del navegador en HTTP/1.1. Si se usa HTTP/2 o superior, el límite de conexiones deja de ser un problema. Cuando el rendimiento es importante, se puede elegir una solución más flexible y con menos sobrecarga usando fetch y ReadableStream

  • Debido a la simplicidad de SSE, muchos desarrolladores no usan una implementación adecuada y terminan parseando los chunks de datos con expresiones regulares. Esto puede ser problemático porque SSE admite comentarios dentro del stream

  • Data-star.dev es una librería de frontend enfocada en hacer streaming de respuestas de hipermedia mediante SSE. Fue desarrollada usando Go y NATS como tecnologías de backend, y es compatible con todas las implementaciones de SSE

  • SSE no está subestimado. De hecho, Open AI lo usa para streaming de completions. Implementar SSE en un codebase de ReactJS fue difícil, y en ese momento Axios no lo soportaba, así que tuvieron que usar fetch nativo

  • Cuando implementaron SSE en un proyecto web, el sitio dejaba de funcionar al abrir más de 6 pestañas. Firefox cuenta las conexiones SSE dentro del límite máximo de 6 conexiones por host, lo que bloquea las solicitudes adicionales

  • SSE está subestimado cuando funciona bien. En un proyecto en el que están trabajando actualmente han tenido dificultades por problemas de autenticación y de keep-alive en túneles. No es un problema del protocolo, pero encontrar una solución ha sido complicado