La tecnología Server-Sent Events (SSE) está subestimada
(igorstechnoclub.com)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
-
Simplicidad de implementación
- Aprovecha el protocolo HTTP estándar y elimina la complejidad de gestionar conexiones WebSocket.
-
Compatibilidad con la infraestructura
- Funciona sin problemas con la infraestructura HTTP existente:
- balanceadores de carga
- proxies
- firewalls
- servidores HTTP estándar
- Funciona sin problemas con la infraestructura HTTP existente:
-
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
- Menor consumo de recursos en comparación con WebSockets:
-
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
- Soporte integrado en el navegador para:
-
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
- El patrón de comunicación unidireccional garantiza:
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
/streammaneja la conexión SSE. generate_random_data()genera continuamente eventos con el formato adecuado.- El tipo MIME
text/event-streamindica el protocolo SSE. stream_with_contextmantiene el contexto de la aplicación Flask.
Lado del cliente (JavaScript)
- El objeto
EventSourcegestiona la conexión SSE. - El handler
onmessageprocesa los eventos recibidos. onerrormaneja los problemas de conexión.- El navegador se encarga de la reconexión automática.
Limitaciones y consideraciones
-
Comunicación unidireccional
- Solo es posible del servidor al cliente
- La comunicación del cliente al servidor requiere solicitudes HTTP separadas
-
Soporte en navegadores
- Tiene buen soporte en navegadores modernos
- En navegadores antiguos puede requerir un polyfill
-
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.
- Manejar los errores de conexión con
-
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
- devolver el header
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
Implementé OpenAI con REST y realmente usé SSE.
Definitivamente pienso adoptarlo en situaciones donde se necesite comunicación unidireccional.
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.
Es una verdadera lástima que OpenAPI no sea compatible con SSE.
Es una muy buena forma de establecer comunicación bidireccional en entornos NAT.
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