Logo GH

WebSockets - SSE

1) Krótki: co i za co

WebSocket (WS/WSS) - uaktualnienie połączenia HTTP do pełnego kanału dupleksowego. Nadaje się do czatów, gier na żywo, współpracy, dwukierunkowej telemetrii.
Serwer-Wysłane zdarzenia (SSE) - strumień w jedną stronę od serwera do przeglądarki (MIME 'text/event-stream'). Idealny do biletów, powiadomień, cytatów, postępu zadań. Klient - 'Na Źródło'.

Reguła wyboru:
  • Musisz wejść od klienta w czasie rzeczywistym (często dużo) → WebSocket.
  • Tylko push aktualizacje z serwera, kompatybilność i prostota są ważniejsze niż SSE →.

2) Sieć i protokoły

2. 1 Transport i kompatybilność

WebSocket: Zaczyna się jako HTTP 'GET... Uaktualnienie: website ocket '(HTTP/1. 1). Dla HTTP/2 możliwe jest RFC 8441 (CONNECT + ': protocol = website ocket'), wsparcie zależy od serwera proxy. Prace na szczycie TLS (WSS) - obowiązkowe w sprzedaży.
SSE: normalna długa odpowiedź HTTP („200 OK”) z transmisją strumieniową. Dobrze przechodzi przez HTTP/1. 1/2/3, kompatybilny z CDN/proxy (jeśli długie połączenia nie są zakończone).

2. 2 Serwery proxy/balancery/CDN

Sprawdź: wsparcie dla długotrwałych połączeń, idles i timeouts, sesje lepkie (jeśli stan jest na węźle).
Dla WS: zawiera 'proxy _ read _ timeout', nagłówki 'upgrade', limity na połączenie.
Dla SSE upewnij się, że serwer proxy nie buforuje odpowiedzi (w przeciwnym razie klient nie zobaczy zdarzeń w czasie).

3) Model wiadomości i kontrola przepływu

WebSocket: ramki tekstowe lub binarne; istnieje 'ping/pong', ale nie ma wbudowanego backpressure - wdrożyć na aplikacji (kolejki, okna, drop-policy).
SSE: zdarzenia tekstowe (UTF-8); klient jest w stanie ponownie połączyć się z opóźnieniem wbudowanym; serwer może określić 'retry:'. Istnieje nagłówek 'id:' i 'Last-Event-ID' do wznowienia z żądanej pozycji.

Ciśnienie wsteczne (praktyki ogólne):
  • Cytuj wychodzące wiadomości na klienta.
  • Ograniczenie kolejki nieprzyjemnych zdarzeń; w przypadku przelewu - odrzut o niskim priorytecie/kruszywo.
  • W przypadku systemu WS należy użyć okna przesuwnego i ACK na poziomie aplikacji.

4) Niezawodność połączeń

4. 1 Wykrywanie i utrzymywanie przy życiu

WS: wysyłać 'ping' co N sekund; luka czasowa - ponownie połączyć z wykładniczym backoff + jitter.
SSE: serwer wysyła „komentarze” :\n' jako bicie serca, dzięki czemu połączenie nie liczy się bezczynnie; Klient się ponownie połączy.

4. 2 Odzyskiwanie przepływu

WS: przechowywać wiadomości offsetowe/sekwencyjne i żądać delta po ponownym połączeniu.
SSE: użyj 'id:' dla każdego zdarzenia i 'Last-Event-ID' w żądaniu - serwer wysyła pominięte zdarzenia.

5) Uwierzytelnianie i autoryzacja

JWT Bearer in request URL (WS) jest niepewny (wycieki w dziennikach). Użyj nagłówka (za pośrednictwem głównego uścisku dłoni HTTP) lub plików cookie z flagami 'Secure', 'Only', ' Site'.
mTLS (zwłaszcza dla B2B) jest możliwe, a także podpisanie (HMAC) nad oryginalnym żądaniem.
W przypadku SSE z plikami cookie należy pamiętać o CORS („Access-Control-Permit-Origin”, „Permit-Credentials”).

Token rotacja: Nie odciąć strumienia. Przepustka „wkrótce wygaśnie” → klient ponownie otworzy połączenie z nowym tokenem.

6) Format danych i kompresja

WebSocket: umożliwia staranne opróżnianie permesage (CPU); unikać kompresji już skompresowanych formatów (Proto, Avro). Ładunek binarny jest bardziej ekonomiczny niż JSON.
SSE: jest to tekst; w przypadku dużych danych wyślij link do zasobu REST/gRPC lub plików kawałkowych; transport gzip dla SSE - odpowiedni, ale zegarek do buforowania w serwerze proxy/CDN.

7) Skalowanie i wentylacja

7. 1 Skalowanie poziome

Zachowaj aplikację bez usterek na ponowne uruchomienie. Status połączenia - w warstwie przedniej; dane - od brokera.
Sticky (hash według sesji/użytkownika) jest potrzebny, jeśli istnieją lokalne kolejki.
Ideałem jest przód bezpaństwowca: węzeł tylko multipleksuje subskrypcje; wydarzenia pochodzą ze wspólnego pubu/sub.

7. 2 Pub/Sub i Brokers

Dla szerokiego wentylatora użyj Kafka/NATS/Redis Streams.
Warstwa „Fanout Gateway” zapisuje się do tematów i puszek klientów za pośrednictwem WS/SSE.
Użyj klucza routingowego (na przykład '‡ Id',' matchId'), aby zrównoważyć obciążenie między węzłami.

8) Konfiguracje produkcji

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 (ważne dla wyłączenia buforowania)

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 kubernety (adnotacje Ingress, Ingress NGINX)

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) Przykłady kodów

9. 1 klient SSE (przeglądarka)

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 Serwer SSE (węzeł. 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 Klient WebSocket (przeglądarka)

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) Bezpieczeństwo i ograniczenie

Ograniczenie prędkości na połączenie i na użytkownika: ograniczenie szybkości przychodzących wiadomości (WS) i szybkości przepływu wychodzącego (WS/SSE).
Kontyngent według okresu użytkowania połączenia i całkowitego ruchu.
Limit rozmiaru wiadomości, maks ./sec.
Filtry WAF/bot na etapie uścisku dłoni; zabezpieczenie przed zalaniem połączeń (wiele krótkich połączeń).
Izolacja lokatora/obszaru nazw: poszczególne puli zasobów.

11) Obserwowalność

Metryka:
  • „połączenia _ active”, „connections _ new _ total”, „bytes _ in/out”,
  • „messages _ in/out _ total”, „dropped _ messages _ total”,
  • „reconnects _ total”, „latency _ delivery _ ms {p50, p95, p99}”.
  • Dzienniki: IP/UA, viaId/tenantId, powód zamknięcia („close _ code”), czas trwania.
  • Śledzenie: powiązać zdarzenia z oryginalnym poleceniem (identyfikatory korelacji); W przypadku WS należy użyć „wirtualnych” przęseł masła.

12) Niuanse operacyjne

Zakończenie TLS bliżej klienta (CDN/edge).
Proaktywny obrót połączeń (graceful) podczas ubogich: daj flagę „reconnect”.
Shading na klucz, aby równomiernie rozprowadzić „gorące” kanały.
Migawki stanu dla późnych abonentów (migawka + delta).
Ostatnia wartość pamięci podręcznej (szczególnie SSE) - przydatna dla zimnego klienta.

13) Anty-wzory

Strumieniowo duże kawałki binarne przez SSE lub JSON przez WS - użyj HTTP pobierz i link w wiadomości.
Autoryzacja tylko w momencie połączenia i brak ponownych kontroli na długie sesje.
Globalny lepki niepotrzebnie → nierównowaga i gorące węzły.
Wyłączone czasy/limity → zamrożone połączenia zjadają pulę.
Serwer proxy SSE/buforowanie CDN → „czas rzeczywisty” staje się minutą opóźnienia.
Brak sekwencji/przesunięcia → po ponownym połączeniu klient traci integralność danych.

14) Lista kontrolna wdrażania

  • Wybiera się WS (dwukierunkowy) lub SSE (jednostronny).
  • Skonfigurowane timeouts, utrzymać i ponownie połączyć (backoff + jitter).
  • Zaprojektowana sekwencja/przesunięcie oraz (dla SSE) 'id'/' Last-Event-ID'.
  • Wielkość/prędkość/połączenia/kwoty, ochrona DoS zdefiniowana.
  • Proxy/ingress config: upgrade, proxy_buffering off (SSE), read/send timeouts.
  • Skalowanie: pub/sub broker, wentylator-out gateway, lepki tylko w razie potrzeby.
  • Uwierzytelnianie: bezpieczny transfer tokenów, obrót bez przerwy.
  • Obserwowalność: mierniki, kłody, ślady; deski rozdzielcze i wpisy.
  • Plan wydania: wdzięczne połączenia drenażowe, sygnał klienta do ponownego połączenia.
  • Dni gry: przerwy w sieci, krople do węzłów, przeciążenie maklerskie, długie RTT.

15) FAQ

Czy SSE można buforować za pośrednictwem CDN?
Zazwyczaj nie: To spersonalizowany przepływ. Dla kanałów publicznych - być może z krótkim TTL i pękniętą dostawą, ale łatwo jest złamać „w czasie rzeczywistym”.

Czy WebSocket działa na szczycie HTTP/2/3?
Przeglądarka WS zaczyna się od HTTP/1. 1-upgrade; jest RFC 8441 dla h2, wsparcie w serwerze proxy/serwer jest wymagane oddzielnie. Z h3 - w ruchu; do przesyłania strumieniowego, h3 ma WebTransport, ale jest to inny interfejs API.

gRPC vs WS dla przeglądarki?
Czysta przeglądarka nie mówi gRPC; potrzebuje gRPC-Web przez wysłannika. W przypadku interaktywnych interfejsów użytkownika WS + REST jest często łatwiejszy.

16) Kwoty całkowite

WebSocket - kiedy potrzebujesz dialogu w czasie rzeczywistym i kompaktowego kanału dwukierunkowego.
SSE - gdy potrzebujesz prostego i niezawodnego pchania z serwera do klienta, minimalnej złożoności i automatycznego ponownego połączenia.
Sukces w sprzedaży to poprawne czasy i limity, odzyskiwanie z offsetu, pub/sub fan-out, poprawne ustawienia proxy i wyraźna obserwowalność.

Contact

Skontaktuj się z nami

Napisz do nas w każdej sprawie — pytania, wsparcie, konsultacje.Zawsze jesteśmy gotowi pomóc!

Telegram
@Gamble_GC
Rozpocznij integrację

Email jest wymagany. Telegram lub WhatsApp są opcjonalne.

Twoje imię opcjonalne
Email opcjonalne
Temat opcjonalne
Wiadomość opcjonalne
Telegram opcjonalne
@
Jeśli podasz Telegram — odpowiemy także tam, oprócz emaila.
WhatsApp opcjonalne
Format: kod kraju i numer (np. +48XXXXXXXXX).

Klikając przycisk, wyrażasz zgodę na przetwarzanie swoich danych.