Konrad Kowalski (rootsher)Principal Platform & Reliability Architect000110011111001110111010000100000001111000000111

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:

text
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:

text
30 seconds

polling co 20-30 sekund może być właściwym rozwiązaniem.

Jeżeli:

text
< 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

text
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

text
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

text
server -> client

SSE daje gotowy event framing i reconnect.

Obie strony stale wysyłają wiadomości

text
client <-> server

WebSocket jest naturalnym wyborem.

Potrzebujemy różnych klas transportu

text
reliable streams
+
independent streams
+
unreliable datagrams

Wtedy warto rozważyć WebTransport.

Decision tree

text
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

MechanizmModelKierunekConnection stateDelivery model
Pollingrepeated request/responseclient-drivenkrótkiHTTP
Long Pollingdelayed request/responseserver-triggered responsedługi requestHTTP
HTTP Streamingstreaming responseserver to clientdługi responsebytes/stream
SSEevent stream over HTTPserver to clientpersistentreliable ordered stream
WebSocketmessage channelbidirectionalpersistentreliable ordered
WebTransportstreams + datagramsbidirectionalpersistent sessionreliable + 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:

text
events
acknowledgements
rooms
namespaces
reconnect
broadcasting
transport fallback

Architektura jest bliższa:

text
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:

text
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ę:

text
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:

text
request
response
forget

przechodzimy do:

text
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.