GH GambleHub

WebSocket streaming y eventos

TL; DR

Flujo de trabajo = canal confiable (WSS) + offsets resumibles + eventos idempotentes + límites estrictos y retroceso. Haga: JWT autenticación, autorización de topics, heartbeats, seq/offset + resume-token, at-least-once + dedoup. Para la escala - charding por usuario/tenant, sticky-routing, y la cola (Kafka/NATS/Redis Streams) como fuente de la verdad.

1) Casos de negocio de iGaming (que es realmente streamim)

Balance/límites: cambios instantáneos de balance, límites de RG, bloqueos.
Apuestas/rondas/resultados: confirmación, estado, cálculo de ganancias.
Torneos/liderazgos: posiciones, temporizadores, eventos de premios.
Pagos: estado de payout/refund, banderas KYC/AML - como notificaciones (y las críticas permanecen en NAT + webhooks).
Eventos de servicio: mensajes de chat, banners de inserción, estados de sesión, mantenimiento.

2) Protocolo y conexión

Sólo WSS (TLS 1. 2+/1. 3). Máximo de 1 conexión activa por dispositivo/sesión predeterminada.
Ping/Pong: el cliente es un 'ping' cada 20-30 s, el tiempo de respuesta es de 10 s. El servidor restablece la conexión a 3 tiempos seguidos.
Compresión: 'permessage-deflate', límite de tamaño de fotograma (por ejemplo, ≤ 64 KB).
Formato de carga útil: JSON para exteriores, Protobuf/MsgPack para interiores/móviles.

3) Autenticación y autorización

Handshake con JWT en query/header ('Sec-WebSocket-Protocol '/' Authorization'), token TTL corto (≤ 15 min), refresh por out-of-band (NAT).
Tenant-scoped claims: `sub`, `tenant`, `scopes`, `risk_flags`.
ACL en topics/canales: suscripción sólo a los 'topic' permitidos (por ejemplo: 'user: {id}', 'tournament: {id}', 'game: {table}').
Intersección de la conexión cuando el token caduca: «ventana suave» 60 s.

4) Modelo de suscripción

El cliente, después de conectar, envía comandos:
json
{ "op":"subscribe", "topics":["user:123", "tournament:456"], "resume_from":"1748852201:987654" }
{ "op":"unsubscribe", "topics":["tournament:456"] }

'resume _ from' - offset (ver § 5) si el cliente restaura la conexión.
El servidor responde ack/nack, ACLs que no han salido - en 'nack' con 'reason'.

5) Garantías de envío y resumen

Objetivo: at-least-once por canal + idempotencia en el cliente.

Cada evento tiene un 'seq' monótono dentro de un «lote» (normalmente user/room) y un 'event _ id' global para el dedoop.
En re-connect, el cliente pasa 'resume _ from' = el último 'seq' (o 'offset' del broker) confirmado. El servidor carga los eventos perdidos desde el «origen de la verdad» (Kafka/NATS/Redis Streams).
Si el lag supera la retention (por ejemplo, 24 h): el servidor envía un 'snapshot' de estado y un nuevo 'seq'.

Semántica del cliente:
  • Almacenar 'last _ seq '/' event _ id' en almacenamiento durable (IndexedDB/Keychain).
  • Dedoup por 'event _ id', omitir eventos con 'seq ≤ last_seq', detectar agujeros (gap) → consultas de snapshot auto-' resync'.

6) Esquema de mensaje (envelope)

json
{
"ts": "2025-11-03T12:34:56. 789Z",
"topic": "user:123",
"seq": "1748852201:987654",   // partition:offset
"event_id": "01HF..",      // UUID/KSUID
"type": "balance. updated",
"data": { "currency":"EUR", "delta"--5. 00, "balance":125. 37 },
"trace_id": "4e3f.., "//for correlation
"signature": "base64 (hmac (...)) "//optional for partners
}

'tipo' es una taxonomía de dominio (ver diccionario de eventos).
PII/PCI - Eliminar/enmascarar a nivel de puerta de enlace.

7) Backpressure, cuotas y protección contra clientes «caros»

Server → Client: per-connection nat-queue con «ventana deslizante». Desbordado: restablece las suscripciones a topics o disconnect «ruidosos» con el código '1013 '/' policy _ violation'.
Client → Server: límites en 'subscribe/unsubscribe' (por ejemplo, ≤ 10/sec), límite de lista de topics (≤ 50), intervalo mínimo de repetición de suscripción.
Rate limits por IP/tenant/clave. Anomalías → bloqueo temporal.
Prioridad: eventos vitales (balance, límites RG) - cola prioritaria.

8) Protección y seguridad

Perfil WAF/bot en endpoint handshake, lista de orígenes permitidos.
mTLS entre la puerta de enlace edge y los nodos de streaming.
Protección DoS: cookies SYN en L4, límites en el número de WS abiertos/intervalo keep-alive.
Anti-replay: 'timestamp' en la firma de carga útil opcional (para socios) con una ventana válida de 5 min.
Aislamiento de inquilinos: charding físico/lógico, llaves/tokens per-tenant.

9) Arquitectura de transporte

Puerta de enlace (edge): terminate TLS, authN/Z, cuotas, enrutamiento por lote.
Nodos Stream: stateless workers con routing sticky por 'hash (user_id)% N'.
Corredor de eventos: Kafka/NATS/Redis Streams es la fuente de la verdad y el buffer de réplica.
State-service: almacena snapshots (balance, posiciones en el torneo).
Multirregión: activo-activo; GSLB para la región más cercana; home-region se fija en el inicio de sesión; con feilover es un resumen «frío» de otra región.

10) Orden, coherencia, idempotencia

El ordenamiento está garantizado dentro del lote (user/room), no globalmente.
Consistencia: un evento puede llegar antes de una respuesta NAT; UX debe ser capaz de vivir con un estado intermedio (optimistic UI + reconciliation).
Idempotencia: volver a procesar 'event _ id' no cambia el estado del cliente.

11) Errores, reconnect y «tormenta»

Códigos de cierre: '1000' (normal), '1008' (policy), '1011' (internal), '1013' (server overload).
Cliente exponencial backoff + jitter: 1s, 2s, 4s... max 30s.
Durante reconnectaciones masivas ("thundering herd'): el servidor da respuestas 'retry _ after' y 'grises' con una pista para usar SSE fallback para read-only.

12) Caché y snapshots

Cada suscripción puede comenzar con un snapshot de estado actual, luego con un flujo de eventos diff.
Versionar el esquema 'data _ version' y la compatibilidad (la extensión de campo no rompe clientes).

13) Observabilidad y SLO

Métricas:
  • Conexiones: activas, instaladas/segundos, distribuidas por arrendatarios/regiones.
  • Entrega: p50/p95 retraso del corredor al cliente, drop-rate, resend-rate.
  • Fiabilidad: proporción de currículos exitosos sin snapshot, detector de gap.
  • Errores: 4xx/5xx en el handshake, códigos de cierre, hits de límite.
  • Carga: comandos RPS 'subscribe', tamaño de cola, CPU/NET.
SLO puntos de referencia:
  • Establecimiento de WS p95 ≤ 500 ms (dentro de la región).
  • End-to-end latency eventos p95 ≤ 300 ms (user-partition).
  • Resume success ≥ 99%, message loss = 0 (по at-least-once).
  • Uptime stream-endpoint ≥ 99. 95%.

14) Administración de esquemas y versiones

Diccionario de eventos con propietarios, ejemplos y semántica.
Evolución «suave»: sólo la adición de campos opcionales; eliminación - después de '@ deprecated' período.
Pruebas contractuales contra clientes SDK, linternas en JSON Schema/Protobuf.

15) Incidencias de Playbucks (incrustar en tu playbook compartido)

Latency Growth: cambiar lotes a nodos redundantes, aumentar el tamaño del batch del bróker, habilitar la priorización de eventos vitales.
Tormenta de reconnectaciones: activar 'retry _ after', elevar temporalmente los límites de handshake, habilitar el follback SSE.
Fuga de tokens: rotación de JWKS, revocación de tokens afectados, reconnect forzado con re-auth.
Pérdida de lote de broker: puesta en modo snapshot, replay después de la recuperación.

16) Mini especificación API (simplificado)

Handshake (HTTP GET → WS):

GET /ws? tenant=acme&client=web
Headers:
Authorization: Bearer <JWT>
X-Trace-Id: <uuid>
Comandos de cliente:
json
{ "op":"subscribe",  "topics":["user:123"], "resume_from":"1748852201:42" }
{ "op":"unsubscribe", "topics":["user:123"] }
{ "op":"ping", "ts":"2025-11-03T12:34:56Z" }
Respuestas del servidor:
json
{ "op":"ack", "id":"subscribe:user:123" }
{ "op":"event", "topic":"user:123", "seq":"1748852201:43", "type":"balance. updated", "data":{...} }
{ "op":"snapshot", "topic":"user:123", "seq":"1748852201:42", "state":{...} }
{ "op":"error", "code":"acl_denied", "reason":"no access to topic tournament:456" }
{ "op":"pong", "ts":"..." }

17) Lista de verificación de la UAT

  • Resumen de offset después de 1/10/60 minutos de downtime del cliente.
  • Dedoop: volver a entregar el mismo 'event _ id' no cambia el estado.
  • El detector gap → un 'snapshot' automático y una alineación.
  • Cuotas y retroceso: el cliente cargado recibe policy-disconnect.
  • Multirregión: failover de la región con preservación offset.
  • Seguridad: token rockero caducado por JWT, intento de suscripción fuera de la ACL.
  • El RG/balance del evento viene antes/después de NAT - IU correctamente «cosido».

18) Errores frecuentes

No hay 'seq/offset' y reanudación - perder eventos y confianza.
Mezclar comandos de pago críticos en mutaciones WS: use NAT.
Ausencia de backpressure/cuotas - Conexiones «suspendidas» y avalancha de memoria.
El ordenamiento mundial es caro y no es necesario; suficiente orden en el partido.
La lógica de PII en los eventos es la violación de la privacidad y PCI/GDPR.
Falta de diccionario de eventos y versionamiento: los clientes se rompen.

Resumen

Los streams WebSocket proporcionan señales reactivas UX y en línea si se construyen como un canal resumible, seguro y limitado: WSS + mTLS/JWT, ACL en topics, seq/offset + resume, at-least-once con dedupom, backpressure/cupos, broker como fuente de verdad, observabilidad y SLO. Así que los streams siguen siendo rápidos para el usuario y manejables para la plataforma, sin compromisos de seguridad y dinero.

Contact

Póngase en contacto

Escríbanos ante cualquier duda o necesidad de soporte.¡Siempre estamos listos para ayudarle!

Iniciar integración

El Email es obligatorio. Telegram o WhatsApp — opcionales.

Su nombre opcional
Email opcional
Asunto opcional
Mensaje opcional
Telegram opcional
@
Si indica Telegram, también le responderemos allí además del Email.
WhatsApp opcional
Formato: +código de país y número (por ejemplo, +34XXXXXXXXX).

Al hacer clic en el botón, usted acepta el tratamiento de sus datos.