Polling, Streaming, SSE, WebSocket czy WebTransport?
- data
- kategoria
- Backend
- także w
- Frontend · System Design
- czytanie
- 2 min / 446 słów
Nie istnieje technologia „do realtime”.
Istnieją różne wymagania dotyczące:
latency
direction
frequency
ordering
reliability
connection lifetime
Dopiero ich kombinacja prowadzi do mechanizmu.
Zacznij od latency budget
Pierwsze pytanie:
jak stare mogą być dane?
Jeżeli odpowiedź brzmi:
30 seconds
polling co 20-30 sekund może być właściwym rozwiązaniem.
Jeżeli:
< 500 ms
ciągłe odpytywanie zaczyna być mniej atrakcyjne.
Realtime jest więc przede wszystkim wymaganiem dotyczącym freshness.
Kto inicjuje dane?
Klient okresowo potrzebuje aktualnego snapshotu
client -> server
Wybierz polling.
Typowe przypadki:
- status batch joba,
- dashboard bez ścisłego SLA,
- availability checks.
Serwer wie, kiedy pojawia się zmiana
Long polling może być sensowny, szczególnie gdy chcemy pozostać przy klasycznym request/response.
Jeden request produkuje dane stopniowo
request
<- chunk
<- chunk
<- chunk
<- done
To raw HTTP streaming.
Typowy przykład:
- AI response,
- logs,
- eksport/generowanie wyniku.
Serwer publikuje eventy przez dłuższy czas
server -> client
SSE daje gotowy event framing i reconnect.
Obie strony stale wysyłają wiadomości
client <-> server
WebSocket jest naturalnym wyborem.
Potrzebujemy różnych klas transportu
reliable streams
+
independent streams
+
unreliable datagrams
Wtedy warto rozważyć WebTransport.
Decision tree
How fresh must data be?
│
├── seconds/minutes are OK
│ └── Polling
│
└── low latency
│
├── one finite response produced gradually
│ └── HTTP Streaming
│
├── long-lived server to client events
│ └── SSE
│
└── frequent bidirectional communication
│
├── reliable ordered messages are enough
│ └── WebSocket
│
└── need multiple streams / datagrams
└── WebTransport
Long polling pozostaje użytecznym wariantem pomiędzy pollingiem i trwałym streamem, zwłaszcza przy ograniczeniach kompatybilności lub istniejącej infrastrukturze.
Porównanie
| Mechanizm | Model | Kierunek | Connection state | Delivery model |
|---|---|---|---|---|
| Polling | repeated request/response | client-driven | krótki | HTTP |
| Long Polling | delayed request/response | server-triggered response | długi request | HTTP |
| HTTP Streaming | streaming response | server to client | długi response | bytes/stream |
| SSE | event stream over HTTP | server to client | persistent | reliable ordered stream |
| WebSocket | message channel | bidirectional | persistent | reliable ordered |
| WebTransport | streams + datagrams | bidirectional | persistent session | reliable + unreliable |
Socket.IO nie jest kolejnym transportem
Jeżeli wybierzemy WebSocket, nadal pozostaje pytanie:
ile protokołu aplikacyjnego chcemy napisać sami?
Native WebSocket daje kanał.
Socket.IO daje wyższy model:
events
acknowledgements
rooms
namespaces
reconnect
broadcasting
transport fallback
Architektura jest bliższa:
application
|
v
Socket.IO
|
v
Engine.IO
|
v
WebSocket / HTTP long-polling
Dlatego Socket.IO i WebSocket nie są alternatywami na tym samym poziomie.
Socket.IO jest wyborem warstwy komunikacyjnej nad transportem.
GraphQL Subscriptions też są wyżej
GraphQL definiuje subscription jako długotrwałą operację produkującą response stream w reakcji na kolejne eventy.
Nie definiuje jednak konkretnego transportu.
Możliwe jest więc:
GraphQL Subscription
|
v
WebSocket
ale również inne mapowania transportowe.
To application-level semantics, nie odpowiednik WebSocketa.
A WebRTC?
WebRTC DataChannel również daje realtime data communication, ale zmienia topologię:
frontend A <-> frontend B
Backend może brać udział w signalingu, STUN/TURN i zestawieniu sesji, ale docelowy przepływ danych może być peer-to-peer.
Dlatego WebRTC należy do osobnej historii.
Najważniejszy trade-off
Każdy krok w kierunku persistent realtime zwiększa odpowiedzialność systemu.
Z:
request
response
forget
przechodzimy do:
connection identity
liveness
heartbeat
reconnect
resume
fan-out
backpressure
deploy draining
state recovery
To jest koszt, który powinien być uzasadniony wymaganiami produktu.
Najprostszy poprawny mechanizm zwykle wygrywa.
Nie dlatego, że realtime jest trudne.
Dlatego, że trwała komunikacja zmienia system z serii niezależnych operacji w długotrwałą relację pomiędzy klientem, siecią i backendem.
I to jest właściwa granica architektoniczna tej serii.