La comunicación en tiempo real está en todas partes: chatbots en vivo, transmisiones de datos o mensajes instantáneos. WebSockets son un poderoso habilitador de esto, pero ¿cuándo debe usarlos? ¿Cómo funcionan y cómo difieren de las solicitudes HTTP tradicionales?
Este artículo se inspiró en una entrevista reciente de diseño del sistema, “diseñar una aplicación de mensajería en tiempo real”, donde me topé con algunos conceptos. Ahora que he cavado más profundo, me gustaría compartir lo que he aprendido para que puedas evitar los mismos errores.
En este artículo, exploraremos cómo WebSockets encajan en la imagen más grande de la comunicación cliente -servidor. Discutiremos lo que hacen bien, dónde se quedan cortos y, sí, cómo diseñar una aplicación de mensajería en tiempo real.
Comunicación cliente-servidor
En esencia, la comunicación cliente-servidor es el intercambio de datos entre dos entidades: un cliente y un servidor.
El cliente solicita datos, y el servidor procesa estas solicitudes y devuelve una respuesta. Estos roles no son exclusivos: los servicios pueden actuar como un cliente y un servidor simultáneamente, dependiendo del contexto.
Antes de sumergirnos en los detalles de WebSockets, retrocedamos y exploremos la imagen más grande de los métodos de comunicación cliente-servidor.
1. Polling corto
Las encuestas cortas es el enfoque más simple y más familiar.
El cliente envía repetidamente solicitudes HTTP al servidor a intervalos regulares (por ejemplo, cada pocos segundos) para verificar los datos nuevos. Cada solicitud es independiente y una dirección (cliente → servidor).
Este método es fácil de configurar, pero puede desperdiciar recursos si el servidor rara vez tiene datos nuevos. Úselo para menos aplicaciones sensibles al tiempo donde las encuestas ocasionales son suficientes.
2. Largas encuestas
Long Polling es una mejora sobre las encuestas cortas, diseñada para reducir el número de solicitudes innecesarias. En lugar de que el servidor responda inmediatamente a una solicitud de cliente, el servidor Mantiene la conexión abierta Hasta que estén disponibles nuevos datos. Una vez que el servidor tiene datos, envía la respuesta y el cliente establece inmediatamente una nueva conexión.
Las largas encuestas también son apátrida y uno direccional (Cliente → servidor).
Un ejemplo típico es una aplicación de recolección de viajes, donde el cliente espera una actualización de coincidencia o reserva.
3. Webhooks
Webhooks voltea el script haciendo del servidor el iniciador. El servidor envía Publicación HTTP Solicitudes a un punto final definido por el cliente siempre que ocurran eventos específicos.
Cada solicitud es independiente y no confía en una conexión persistente. Los webhooks también son uno direccional (servidor al cliente).
Los webhooks se usan ampliamente para notificaciones asincrónicas, especialmente cuando se integran con servicios de terceros. Por ejemplo, los sistemas de pago utilizan Webhooks para notificar a los clientes cuando cambia el estado de una transacción.
4. Eventos del servidor (SSE)
SSES son un Protocolo de transmisión de eventos nativo basado en HTTP Eso permite a los servidores impulsar las actualizaciones en tiempo real a los clientes en un solo conexión persistente.
SSE funciona usando el EventSource API, que lo hace fácil de implementar en aplicaciones web modernas. Es uno direccional (servidor a cliente) e ideal para situaciones en las que el cliente solo necesita recibir actualizaciones.
SSE es adecuado para aplicaciones como plataformas comerciales o actualizaciones deportivas en vivo, donde el servidor empuja datos como precios de acciones o puntajes en tiempo real. El cliente no necesita enviar datos al servidor en estos escenarios.
Pero, ¿qué pasa con la comunicación bidireccional?
Todos los métodos anteriores se centran en el flujo individual. Para los verdaderos intercambios de dos vías en tiempo real, necesitamos un enfoque diferente. Ahí es donde brillan WebSockets.
Vamos a sumergirnos.
¿Cómo funcionan WebSockets?
WebSockets Enable Comunicación bidireccional en tiempo realhaciéndolos perfectos para aplicaciones como aplicaciones de chat, notificaciones en vivo y juegos en línea. A diferencia del modelo tradicional de solicitud de respuesta HTTP, WebSockets crea un persistente Conexión, donde tanto el cliente como el servidor pueden enviar mensajes de forma independiente sin esperar una solicitud.
La conexión comienza como una solicitud HTTP normal y se actualiza a una conexión WebSocket a través de un apretón de manos.
Una vez establecido, utiliza una sola conexión TCP, que funciona en los mismos puertos que HTTP (80 y 443). Los mensajes enviados a través de WebSockets son pequeños y livianos, lo que los hace eficientes para los casos de uso de baja interactividad de baja latencia.
Las conexiones de WebSocket siguen un formato de URI específico: ws:// para conexiones regulares y wss:// para conexiones seguras y cifradas.
¿Qué es un apretón de manos?
Un apretón de manos es el proceso de Inicializar una conexión entre dos sistemas. Para WebSockets, comienza con una solicitud HTTP Get del cliente, solicitando una actualización de protocolo. Esto garantiza la compatibilidad con la infraestructura HTTP antes de la transición a una conexión de WebSocket persistente.
- El cliente envía una solicitud, con encabezados que parecen:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Upgrade– señala la solicitud para cambiar el protocoloSec-WebSocket-Key– Cadena codificada Base64 generada al azar utilizada para la verificación de apretones de manosSec-WebSocket-Protocol(Opcional): enumera los subprotocolos que el cliente admite, lo que permite que el servidor elija uno.
2. El servidor responde a la resumen
Si el servidor admite WebSockets y acepta la actualización, responde con un 101 protocolos de conmutación estado. Encabezados de ejemplo:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Accept– Base64 codificado hash del clienteSec-WebSocket-Keyy un guía. Esto asegura que el apretón de manos sea seguro y válido.
3. Validación de apretón de manos
Con el 101 Switching Protocols Respuesta, la conexión WebSocket se establece correctamente y tanto el cliente como el servidor pueden comenzar a intercambiar mensajes en tiempo real.
Esta conexión permanecerá abierta hasta que cualquiera de las partes la cierre explícitamente.
Si algún código que no sea 101 se devuelve, el cliente tiene que finalizar la conexión y el apretón de manos de WebSocket fallará.
Aquí hay un resumen.

Casos de uso de WebSocket
Hemos hablado sobre cómo WebSockets habilita la comunicación bidireccional en tiempo real, pero ese sigue siendo un término bastante abstracto. Vamos a clavar algunos ejemplos reales.
Las redes web se usan ampliamente en herramientas de colaboración en tiempo real y aplicaciones de chat, como Excalidraw, Telegram, WhatsApp, Google Docs, Google Maps y la sección de chat en vivo durante una transmisión en vivo de YouTube o Tiktok.
Comercio
1. Tener una estrategia de respuesta si se terminan las conexiones
WebSockets no se recuperan automáticamente si la conexión se termina debido a problemas de red, bloqueos del servidor u otras fallas. El cliente debe detectar explícitamente la desconexión e intentar restablecer la conexión.
Larga electricidad a menudo se usa como copia de seguridad, mientras que una conexión WebSocket intenta restablecer.
2. No está optimizado para transmitir datos de audio y video
Los mensajes de WebSocket están diseñados para enviar Pequeños mensajes estructurados. Para transmitir datos de medios grandes, una tecnología como WebRTC es más adecuada para estos escenarios.
3. Los websChets son estancados, por lo tanto, la escala horizontalmente no es trivial
WebSockets son de estadolo que significa que el servidor debe mantener una conexión activa para cada cliente. Esto hace que la escala horizontal sea más compleja en comparación con el HTTP sin estado, donde cualquier servidor puede manejar una solicitud del cliente sin mantener el estado persistente.
Necesitará una capa adicional de mecanismos de pub/sub para hacer esto.
Diseñar una aplicación de mensajería en tiempo real
Ahora veamos cómo se aplica esto en el diseño del sistema. He cubierto tanto la solución simple (indescriptible) como una escalada horizontalmente.

Aplicación de servidor único no escalable: ¿Cómo chatan dos usuarios en tiempo real?
- Todos los usuarios se conectan a través de WebSocket a un servidor. El servidor contiene una asignación en memoria de
userID : WebSocket conn 1 - User1 envía el mensaje a través de su conexión WebSocket al servidor.
- El servidor escribe el mensaje al MessageDB (Persistencia primero).
- El servidor luego mira hacia arriba
user2 : WebSocket conn 2en It’s en Memory Map. Si el usuario2 está en línea, entrega el mensaje en tiempo real. - Si el usuario2 está fuera de línea, el servidor escribe en INBOXDB (una tienda de mensajes no entregados). Cuando User2 devuelve en línea, el servidor obtiene todos los mensajes fuera de línea desde InBoBoLDB.
Sistema escalado horizontalmente: ¿Cómo chatan los dos usuarios en tiempo real?
Un solo servidor solo puede manejar tantos websockets concurrentes. Para servir a más usuarios, debe escalar horizontalmente sus conexiones WebSocket.
El desafío clave: si el usuario1 está conectado a Server1 pero User2 está conectado a Server2, ¿cómo sabe el sistema dónde enviar el mensaje?
Redis se puede utilizar como un almacén de datos global que mapea userID : serverID para sesiones activas de WebSocket. Cada servidor actualiza a Redis cuando un usuario se conecta (se conecta en línea) o se desconecta (se desconecta).
Por ejemplo:
-
El usuario1 se conecta al servidor1. Server1 en el mapa de memoria:
user1 : WebSocket connectionServer1 también escribe a Redis:user1 : server1 -
User2 se conecta al servidor2. servidor2 en el mapa de memoria:
user2 : WebSocket connectionServer2 también escribe a Redis:user2 : server2
Flujo de chat de finalización a final: User1 envía un mensaje al usuario2
- User1 envía un mensaje a través de su WebSocket en Server1.
- Server1 pasa el mensaje a un servicio de chat.
- El servicio de chat primero escribe el mensaje a Messagedb para su persistencia.
- El servicio de chat luego verifica a Redis para obtener el estado en línea/fuera de línea del usuario2.
- Si el usuario2 está en líneaEl servicio de chat publica el mensaje a un corredor de mensajes, etiquetándolo con: “User2: Server2”.
- El corredor luego enruta el mensaje al servidor2.
- Server2 busca que sea local en la asignación de memoria para encontrar la conexión WebSocket de User2 y presiona el mensaje en tiempo real sobre ese WebSocket.
- Si el usuario2 está fuera de línea (sin entrada en Redis)El servicio de chat escribe el mensaje en el INBOXDB. Cuando user2 devuelve en línea, el servicio de chat obtendrá todos los mensajes no entregados.
- Cada vez que se abre o cierra una nueva conexión WebSocket, los servidores actualizan Redis.
- Cuando un usuario carga por primera vez la aplicación u abre un chat, el servicio de chat obtiene mensajes históricos (por ejemplo, de los últimos 10 días) de Messagedb. Una capa de caché puede reducir las consultas de DB repetidas.
Algunas consideraciones de diseño importantes:
-
Persistencia primero Todos los mensajes van al DB antes de ser entregado. Si un impulso a WebSocket falla, el mensaje aún es seguro en el DB.
-
Rehacer Víveres solo activo Conexiones para minimizar la sobrecarga. Se puede agregar una réplica para evitar un solo punto de falla.
- La bandeja de entrada DB ayuda a manejar las cajas fuera de línea limpiamente.
-
Abstracción del servicio de chat Los servidores WebSocket manejan conexiones y enrutamiento en tiempo real. La capa de servicio de chat maneja las solicitudes HTTP y todas las escrituras de DB. Esta separación de preocupaciones hace que sea más fácil escalar o evolucionar cada pieza.
-
Asegurar en orden la entrega de mensajes Los flujos de trabajo típicos de “empuje en tiempo real” pueden tener variaciones de red, lo que lleva a que los mensajes lleguen fuera de servicio. Muchos corredores de mensajes también No garantice ordenado estricto. Para manejar esto, a cada mensaje se le asigna una marca de tiempo en la creación. Incluso si los mensajes llegan fuera de servicio, el cliente puede reordenarlos en función de la marca de tiempo.
-
Balanceador de carga L4 BALANTE DE CARGA (TCP) para conexiones de WebSocket pegajosas. Balancador de carga L7 (HTTP) para solicitudes regulares (crud, inicio de sesión, etc.).
Concluir
¡Eso es todo por ahora! Hay mucho más que podríamos explorar, pero espero que esto te haya dado un punto de partida sólido. No dude en dejar sus preguntas en los comentarios a continuación 🙂
Escribo regularmente en Python, Desarrollo de software Y los proyectos que construyo, así que dame un seguimiento para no perderte. Nos vemos en el próximo artículo.