Logo GH

WebSockets и SSE

1) Breve: cosa e per cosa

WebSocket (WS/WSS) è un upgrade di connessione HTTP a un canale pieno-duplex. Adatto per chat, giochi live, collaudo, telemetria bidirezionale.
Server-Sent Events (SSE) - Strame unilaterale da server a browser (MIME 'text/event-stream'). Perfetto per i ticker, le notifiche, la quotazione, il progresso delle attività. Il cliente è «EventSource».

Regola di selezione:
  • È necessario immettere il cliente in tempo reale (spesso e molto) .
  • Solo gli upgrade da server, compatibilità e semplicità sono più importanti di SSE.

2) Rete e protocolli

2. 1 Trasporti e compatibilità

WebSocket, inizia come HTTP 'GET... Upgrade: websocket` (HTTP/1. 1). Per HTTP/2 è possibile RFC 8441 (CONNECT + ': protocol = websocket'), il supporto dipende dal proxy. Funziona sopra TLS (WSS) - Obbligatorio in vendita.
SSE: normale risposta HTTP a lunga durata ('200 OK') con streaming. Va benissimo tramite HTTP/1. 1/2/3, compatibile con il CDN/proxy (a meno che non si avvolgano connettori lunghi).

2. 2 Proxy/bilanciatori/CDN

Controlla il supporto per connessioni a lunga vita, idoli e timeout, sessioni sticky (se lo stato è sul nodo).
Per WS, attivare «proxy _ read _ timeout», «upgrade» - zampe, per la connessione dei limiti.
Per SSE, assicurarsi che il proxy non buffi la risposta (altrimenti il client non vedrà gli eventi in tempo).

3) Modello di messaggi e controllo del flusso

WebSocket - fotogrammi di testo o binari c'è «ping/pong», ma nessun backpressure incorporato - implementare su un'applicazione (code, finestre, drop-policy).
SSE: eventi di testo (UTF-8) il client è integrato per il reconnect con ritardo il server può impostare «retry:». C'è «id:» e il titolo «Last-Event-ID» per riprendere dalla posizione desiderata.

Backpressure (prassi generale):
  • Quotare i messaggi per-client in uscita.
  • Limitare la coda degli eventi non inseriti. In caso di sovraccarico, scartare le priorità basse/aggregare.
  • Per WS, utilizzare la finestra di scorrimento e lo schema ACK a livello di applicazione.

4) Affidabilità delle connessioni

4. 1 Rilevamento e keepalive

WS: invia «ping» ogni n secondi; interruzione di timeout - reconnect con backoff esponenziale + jitter.
SSE: il server invia «commenti» come heartbeat in modo che la connessione non venga considerata idle; Il cliente si riconnetterà da solo.

4. 2 Ripristino del flusso

WS: mantieni i messaggi offset/sequence e richiedi il delta dopo il reconnect.
SSE: usa id: per ogni evento e Last-Event-ID nella query: il server invia gli eventi ignorati.

5) Autenticazione e autorizzazione

JWT Bearer nell'URL query (WS) non è sicuro. Usa il titolo (tramite l'handshake HTTP primario) o i cookie con le bandiere «Secure», «HttpOnly», «SameSite».
È possibile mTLS are (in particolare per B2B) e firmare (HMAC) sopra la richiesta iniziale.
Per SSE con cookie, ricordatevi di KORS ('Access-Control-Allow-Origin', 'Allow-Credentials').

Rotazione del token, non rovinate il buco. Passate «presto scaduto» al cliente di riaprire la connessione al nuovo token.

6) Formato dati e compressione

WebSocket: attivare il permessage-deflate con cautela (CPU) evitare la compressione di formati già compressi (Proto, Avro). Payload binario è più economico di JSON.
SSE: questo è testo; per i dati di grandi dimensioni, inviare un link alla risorsa o ai file chunk. gzip di trasporto per SSE - appropriato, ma tieni d'occhio il buffer in proxy/CDN.

7) Scalabilità e fan out

7. 1 Ridimensionamento orizzontale

Mantenere l'applicazione senza forma per il riavvio. Lo stato delle connessioni è nel fronte-livello. I dati sono del broker.
Sticky (hash per sessione/user) è necessario se ci sono code locali.
Ideale: fronte stateless: il nodo non fa altro che multiplicare le sottoscrizioni. gli eventi vengono dal pub/sub generale.

7. 2 Pub/Sub e broker

Utilizzare Kafka/NATS/Redis Streams per un grande fan-out.
Il livello «Fanout Gateway» si abbona ai topicini e allunga i clienti su WS/SSE.
Utilizzare la chiave di instradamento (ad esempio «userId», «matchId») per bilanciare il carico tra i nodi.

8) Configi di produzione

8. 1 NGINX — WebSocket

nginx map $http_upgrade $connection_upgrade { default upgrade; '' close; }

server {
listen 443 ssl http2;
server_name ws. example. com;

location /ws {
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1. 1;
proxy_read_timeout 75s; # increase for long sessions proxy_send_timeout 15s;
proxy_pass http://ws-backend;
}
}

8. 2 NGINX - SSE (è importante disattivare il buffer)

nginx location /events {
proxy_http_version 1. 1;
proxy_set_header Connection "";
proxy_buffering off; # is critical for proxy_cache off threads;
chunked_transfer_encoding on;
proxy_read_timeout 60m;
proxy_pass http://sse-backend;
}

8. 3 Kubernetes (Ingress Annotations, NGINX Ingress)

yaml metadata:
annotations:
nginx. ingress. kubernetes. io/proxy-read-timeout: "3600"
nginx. ingress. kubernetes. io/proxy-send-timeout: "3600"
nginx. ingress. kubernetes. io/enable-websocket: "true"
nginx. ingress. kubernetes. io/proxy-buffering: "off"  # для SSE

9) Esempi di codice

9. 1 Client SSE (browser)

js const es = new EventSource("/events? channel=odds", { withCredentials: true });

es. addEventListener("message", (e) => {
const data = JSON. parse(e. data);
renderOdds(data);
});

es. addEventListener("error", () => {
//EventSource will reconnect itself; can be shown spinner
});

9. 2 Server SSE (Node. js/Express)

js app. get('/events', (req, res) => {
res. writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
});
res. write ('retry: 3000\n\n') ;//3s backoff to client

const sub = subscribe(req. query. channel, (event) => {
res. write(`id: ${event. id}\n`);
res. write(`event: message\n`);
res. write(`data: ${JSON. stringify(event. payload)}\n\n`);
});

req. on('close', () => sub. unsubscribe());
});

9. 3 Client WebSocket (browser)

js const ws = new WebSocket("wss://ws. example. com/ws");
ws. onopen = () => ws. send(JSON. stringify({ type: "join", room: "chat-1" }));
ws. onmessage = (m) => handle(JSON. parse(m. data));
ws. onclose = () => scheduleReconnect();

10) Sicurezza e limitazione

Rate limiting per connessione e per utente - Limitare la frequenza dei messaggi in ingresso (WS) e la velocità del flusso in uscita (WS/SSE).
Il tempo di vita della connessione e il traffico totale.
Message size limit и max messages/sec.
Filtri WAF/bot nella fase di handshake; Protezione contro la connection flooding (molti connettori brevi).
Isolamento da tenant/namespace: pool di risorse separati.

11) Osservabilità

Metriche:
  • `connections_active`, `connections_new_total`, `bytes_in/out`,
  • `messages_in/out_total`, `dropped_messages_total`,
  • `reconnects_total`, `latency_delivery_ms{p50,p95,p99}`.
  • Loghi: IP/UA, userId/tenantId, motivo di chiusura ('close _ code'), durata.
  • Tracing: collegare gli eventi al comando originale (ID correlati); Per WS, utilizzare span virtuali per batch.

12) Sfumature operative

Terminazione TLS più vicina al client (CDN/edge).
Rotazione proattiva delle connessioni (graceful) durante i depositi - Restituisci il flag di riconnessione.
Scharding su chiave per distribuire equamente i canali hot.
Istantanee di stato per follower recenti (snapshot + delta).
Cache ultimo valore (SSE in particolare) - Utile per il client freddo.

13) Anti-pattern

Strai pezzi binari di grandi dimensioni tramite SSE o JSON WS - Usa il download HTTP e il collegamento nel messaggio.
Autorizzazioni solo al momento della connessione e nessun controllo di penne durante lunghe sessioni.
Sticky globale senza bisogno di squilibri e nodi caldi.
Timeout/limiti disattivati, connettori dipendenti mangiano il pool.
Il buffer SSE proxy/CDN si trasforma in minuti di ritardo.
L'assenza di sequence/offset dopo il reconnect del client perde l'integrità dei dati.

14) Assegno foglio di implementazione

  • Il modello selezionato è WS (bidirezionale) o SSE (unilaterale).
  • Timeout, keepalive e reconnect configurati (backoff + jitter).
  • Sono stati progettati sequence/offset e (per SSE) «id »/« Last-Event-ID».
  • Limiti definiti: dimensioni/velocità/connessioni/quote, protezione da DoS.
  • Config proxy/ingressa: upgrade, proxy _ buffering off (SSE), read/send timeouts.
  • Scalabilità: pub/sub-broker, fan-out-gateway, sticky solo se necessario.
  • Autenticazione: trasmissione sicura del token, rotazione senza dirupo.
  • Osservabilità: metriche, fogli, piste; dashboard e alert.
  • Piano di rilascio: connessioni graceful-drain, segnale al client di connessione penna.
  • Game Days - Scollature della rete, caduta di nodi, sovraccarico del broker, lunghe RTT.

15) FAQ

È possibile memorizzare la cache SSE tramite CDN?
Di solito no, è un flusso personalizzato. Per i canali pubblici, è possibile avere TTL brevi e chunked-delivery, ma è facile inserire «tempo reale».

Il sistema funziona sopra HTTP/2/3?
Il browser WS inizia con HTTP/1. 1-upgrade; RFC 8441 per h2, supporto proxy/server richiesto separatamente. Con h3 - in movimento; per lo streaming nell'h3 c'è un WebTransport, ma questa è un'altra API.

gRPC vs WS per il browser?
Un browser pulito non dice gRPC; Ho bisogno di un contatto con Avvoy. Per le UI interattive è spesso più semplice WS + REST.

16) Riepilogo

WebSocket - quando è necessario un dialogo in tempo reale e un canale bidirezionale compatto.
SSE - Quando si desidera un push semplice e affidabile da server a client, la complessità minima e il reconnect automatico.
Il successo in vendita è il tempo e i limiti corretti, il ripristino offset, il pub/sub-fan-out, le impostazioni proxy corrette e la netta osservabilità.

Contact

Mettiti in contatto

Scrivici per qualsiasi domanda o richiesta di supporto.Siamo sempre pronti ad aiutarti!

Telegram
@Gamble_GC
Avvia integrazione

L’Email è obbligatoria. Telegram o WhatsApp — opzionali.

Il tuo nome opzionale
Email opzionale
Oggetto opzionale
Messaggio opzionale
Telegram opzionale
@
Se indichi Telegram — ti risponderemo anche lì, oltre che via Email.
WhatsApp opzionale
Formato: +prefisso internazionale e numero (ad es. +39XXXXXXXXX).

Cliccando sul pulsante, acconsenti al trattamento dei dati.