Konrad Kowalski (rootsher)Principal Platform & Reliability Architect110010100110000110011111011001011001101111001000

Realtime w przeglądarce: od pollingu do WebTransport

data
kategoria
Backend
także w
Frontend · Networking
czytanie
1 min / 274 słów

Klasyczny model webu jest prosty:

text
client -> request -> server
client <- response <- server

Klient inicjuje komunikację. Serwer odpowiada.

Problem zaczyna się wtedy, gdy stan zmienia się po stronie backendu po zakończeniu requestu.

text
t=0   GET /orders/42 -> processing
t=4   backend: processing -> completed

Skąd frontend ma wiedzieć o zmianie w t=4?

To jest punkt wyjścia tej serii.

Nie będziemy traktować „realtime” jako jednej technologii. Realtime jest wymaganiem dotyczącym maksymalnego akceptowalnego opóźnienia informacji, a nie nazwą protokołu.

text
realtime != WebSocket

Dla jednego systemu aktualizacja po 10 sekundach jest wystarczająco szybka. Dla innego 100 ms jest zbyt wolne.

Przejdziemy przez mechanizmy od najprostszego do najbardziej elastycznego:

text
Polling
  |
  v
Long Polling
  |
  v
HTTP Streaming
  |
  v
Server-Sent Events
  |
  v
WebSocket
  |
  v
WebTransport

Każdy kolejny wynika z konkretnego ograniczenia poprzedniego.

Polling ponawia requesty, nawet gdy nic się nie zmieniło. Long polling pozwala serwerowi opóźnić odpowiedź. HTTP streaming pozwala jednej odpowiedzi zawierać wiele fragmentów danych. SSE dodaje do takiego strumienia standardowy format zdarzeń i reconnect. WebSocket odchodzi od modelu request/response i daje trwały kanał full-duplex. WebTransport idzie dalej: wiele niezależnych streamów oraz datagramy nad HTTP/3.

Po drodze rozdzielimy też warstwy, które często są mieszane:

text
WebSocket
-> protocol + browser API

Socket.IO
-> higher-level realtime protocol/framework

GraphQL Subscription
-> application-level subscription semantics

WebRTC DataChannel
-> peer-to-peer communication

Socket.IO może używać WebSocketu, ale Socket.IO nie jest WebSocketem.

GraphQL Subscription może być dostarczana przez WebSocket albo inny transport, ale sama subskrypcja nie definiuje transportu.

WebRTC rozwiązuje jeszcze inny problem, ponieważ po zestawieniu połączenia dane mogą płynąć peer-to-peer zamiast frontend ↔ backend.

Seria skupia się na komunikacji klient-serwer. Nie będzie tutorialem do budowania chatu ani katalogiem bibliotek.

Interesują nas mechanizmy:

  • kto inicjuje przepływ danych,
  • jak długo żyje request lub connection,
  • gdzie istnieje stan połączenia,
  • jak wygląda framing danych,
  • co dzieje się przy reconnect,
  • jak mechanizm wpływa na load balancer i backend,
  • gdzie pojawia się backpressure,
  • co naprawdę oznacza „push”.

Na końcu wybór technologii powinien wynikać z modelu ruchu:

text
How fresh must data be?
  |
  v
Who sends data?
  |
  v
How often?
  |
  v
Do messages need ordering?
  |
  v
Can old messages be discarded?
  |
  v
What connection state can infrastructure support?

Dopiero potem wybieramy mechanizm.

Nie odwrotnie.