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:
many HTTP requests
-> many independent HTTP streams
Ale streams nadal współdzieliły jedno TCP connection.
HTTP/3 zmienia warstwę pod HTTP.
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:
fetch("/api/users");
Backend nadal semantycznie widzi:
GET /api/users
Nadal istnieją:
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:
HTTP/2 over TCP
loss
|
v
shared TCP byte stream waits
|
v
multiple HTTP streams can stall
kontra:
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:
const user = await fetch("/user");
const orders = await fetch(`/users/${user.id}/orders`);
mamy dependency:
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:
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:
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:
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:
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().