Konrad Kowalski (rootsher)Principal Platform & Reliability Architect100000010011110010110110001101010110000100000100

HTTP/3 i QUIC: ten sam HTTP, inny transport

data
kategoria
Networking
także w
Frontend
czytanie
1 min / 278 słów

HTTP/2 rozwiązał ważny problem:

text
many HTTP requests
-> many independent HTTP streams

Ale streams nadal współdzieliły jedno TCP connection.

HTTP/3 zmienia warstwę pod HTTP.

text
HTTP/2
  |
  v
TCP
  |
  v
TLS

HTTP/3
  |
  v
QUIC
  |
  v
UDP

QUIC integruje mechanizmy transportowe i kryptograficzne potrzebne do bezpiecznej komunikacji.

Semantyka HTTP zostaje

Frontend nadal pisze:

js
fetch("/api/users");

Backend nadal semantycznie widzi:

text
GET /api/users

Nadal istnieją:

text
status codes
headers
cache semantics
content

HTTP/3 nie jest nowym modelem API.

To nowy mapping HTTP semantics na transport.

Streams są niezależniejsze

QUIC ma wiele logicznych streams na poziomie transportu.

Jeżeli dane jednego streamu zostaną zgubione, retransmisja tego streamu nie musi blokować dostarczania danych z innych streams.

Uproszczenie:

text
HTTP/2 over TCP

loss
  |
  v
shared TCP byte stream waits
  |
  v
multiple HTTP streams can stall

kontra:

text
HTTP/3 over QUIC

loss in stream A
  |
  v
stream A waits for recovery

stream B can continue

To usuwa transportowy head-of-line blocking pomiędzy niezależnymi streams.

To nie usuwa latency aplikacji

Jeżeli frontend robi:

js
const user = await fetch("/user");
const orders = await fetch(`/users/${user.id}/orders`);

mamy dependency:

text
request A
  |
  v
response A
  |
  v
request B

HTTP/3 tego nie naprawi.

Network protocol nie usuwa serializacji stworzonej przez aplikację.

To ważne przy performance debugging.

Lepszy transport nie zastępuje poprawnego dependency graph.

Connection establishment

QUIC może zmniejszyć koszt zestawienia bezpiecznej komunikacji w porównaniu z osobnymi etapami TCP + TLS.

Dla powracających connections istnieje również możliwość 0-RTT w określonych warunkach.

Ale 0-RTT ma ograniczenia bezpieczeństwa i semantyki replay, więc nie należy myśleć o nim jako o:

text
every HTTP/3 request starts instantly

To optymalizacja konkretnego etapu zestawiania connection.

Connection migration

TCP connection jest silnie związane z klasycznym tuple adresów i portów.

QUIC używa connection IDs, co pozwala lepiej utrzymywać logiczną sesję przy zmianach ścieżki sieciowej.

Praktyczny przypadek:

text
phone on Wi-Fi
  |
  v
switch to cellular

To szczególnie istotne dla urządzeń mobilnych.

Frontend nie steruje tym bezpośrednio, ale odczuwa efekt jako bardziej odporną warstwę transportową.

Czy frontend musi wykrywać HTTP/3?

Zwykle nie.

Kod aplikacji powinien opierać się na semantyce HTTP:

text
method
status
headers
body

Browser i infrastruktura negocjują protokół transportowy.

DevTools może pokazać użyty protocol, co jest przydatne przy analizie performance.

Ale business logic nie powinna wyglądać tak:

js
if (httpVersion === 3) {
  ...
}

To właśnie siła rozdzielenia warstw.

Teraz możemy złożyć je wszystkie i zobaczyć, co naprawdę wydarza się po pojedynczym fetch().