Bài http-05 kết bằng một giới hạn: HTTP/2 xóa head-of-line blocking ở tầng HTTP, nhưng mọi luồng vẫn chạy trên một kết nối TCP — mất một gói TCP là tất cả luồng bị chặn. Đó là lý do HTTP/3 ra đời, và nó làm điều táo bạo: bỏ TCP, chạy trên UDP thông qua giao thức mới tên QUIC. Bài này giải thích vì sao và đo phần đo được — thành thật rằng curl trong lab không build kèm HTTP/3, nên ta đo những gì khả dụng (trạng thái h3 của curl, Alt-Svc từ site thật, chi phí bắt tay mà QUIC tiết kiệm).
Vấn đề còn lại của HTTP/2: TCP head-of-line blocking
HTTP/2 multiplex nhiều stream trên một kết nối TCP (bài http-05). Nhưng TCP là một dòng byte có thứ tự: nếu một gói TCP bị mất, TCP giữ lại toàn bộ dữ liệu đến sau (kể cả của stream khác) cho tới khi gói mất được truyền lại. Vậy là head-of-line blocking không biến mất — nó dời từ tầng HTTP xuống tầng TCP. Một stream mất gói kéo theo mọi stream khác đứng chờ, dù chúng chẳng liên quan.
QUIC giải quyết bằng cách tự mình quản lý các stream ở tầng vận chuyển (trên UDP), nơi mỗi stream độc lập:
HTTP/3 = HTTP trên QUIC (QUIC chạy trên UDP, không dùng TCP)
+ mỗi stream độc lập ở tầng vận chuyển -> mất gói stream này không chặn stream khác
+ gộp bắt tay transport + mã hóa (TLS 1.3) -> 1 RTT (0-RTT khi nối lại)
+ connection ID -> đổi mạng (wifi<->4G) không đứt kết nối
curl --http3 https://site # cần curl build kèm h3
curl -sI https://site | grep alt-svc # xem site có quảng cáo h3 không

Hình 1: HTTP/2 vẫn dính TCP head-of-line blocking (mọi stream chung một dòng TCP). HTTP/3 chạy trên QUIC (UDP) — mỗi stream độc lập, bắt tay 1 RTT, đổi mạng không đứt. Khám phá h3 qua Alt-Svc.
Đo thật (và những gì lab không chạy được)
curl trong lab build kèm nghttp2 nhưng không có HTTP/3, nên ta không thể gửi request h3 thật ở đây — báo trung thực điều đó và đo phần khả dụng:

Hình 2: curl lab (nghttp2, không HTTP3) — --http3 báo the installed libcurl version doesn't support this. Site thật quảng cáo alt-svc: h3=":443". Bắt tay HTTP/2: TCP xong ~30ms rồi TLS xong ~60ms — hai vòng tuần tự mà QUIC gộp còn một.
Đọc kết quả:
- Trung thực về giới hạn lab: curl 7.88.1 có nghttp2 nhưng không HTTP3; ép
--http3→curl: option --http3: the installed libcurl version doesn't support this. Chạy h3 thật cần curl build kèm thư viện QUIC (quiche/ngtcp2) — không có sẵn ở đây, nên ta không bịa số h3. - Alt-Svc là cách khám phá h3:
curl -sI https://www.cloudflare.com | grep alt-svcchoalt-svc: h3=":443"; ma=86400. Cơ chế: client kết nối bằng h2/h1 trước, server trả headerAlt-Svcquảng cáo rằng nó cũng phục vụ h3 ở cổng 443/UDP với thời hạn nhớma(max-age) giây; lần sau client thử h3. (HTTP/3 không dùng ALPN-trong-TLS để "nâng cấp" như h2, vì nó ở UDP.) - Chi phí QUIC tiết kiệm: đo bắt tay HTTP/2 tới site thật —
time_connect(TCP xong) ~30ms rồitime_appconnect(TLS xong) ~60ms. Đó là hai vòng khứ hồi tuần tự: TCP handshake trước, TLS handshake sau. QUIC gộp thiết lập vận chuyển và mã hóa (TLS 1.3) vào một vòng — và khi nối lại có thể 0-RTT (gửi dữ liệu ngay). Trên mạng độ trễ cao (di động), tiết kiệm một RTT là cảm nhận rõ.
Đánh đổi và lưu ý
HTTP/3 không phải lúc nào cũng nhanh hơn. Trên mạng ổn định ít mất gói, HTTP/2 đã rất tốt — lợi thế h3 rõ nhất khi mạng có mất gói (di động, wifi yếu) nơi TCP HoL blocking đau. Và QUIC chạy ở user space (không phải kernel như TCP) nên tốn CPU hơn một chút; ở quy mô cực lớn điều này đáng cân nhắc.
UDP đôi khi bị chặn. Một số mạng doanh nghiệp/tường lửa chặn hoặc bóp UDP cổng 443. Vì thế HTTP/3 luôn đi kèm fallback: client thử h3, không được thì quay về h2 trên TCP. Alt-Svc chính là cơ chế cho phép "thử h3 nhưng vẫn có đường lui".
Bật h3 chủ yếu ở tầng hạ tầng. Là lập trình viên ứng dụng, bạn hiếm khi "code" h3 — nó do server/CDN/reverse proxy (nginx bản mới, Cloudflare, Caddy) và trình duyệt lo. Việc của bạn thường là bật nó ở proxy/CDN và kiểm bằng alt-svc + công cụ (trình duyệt DevTools cột Protocol hiện h3).
Ba ý mang về
- HTTP/3 chạy trên QUIC (UDP) để xóa TCP head-of-line blocking: HTTP/2 vẫn dính vì mọi stream chung một dòng TCP (mất một gói chặn tất cả); QUIC cho mỗi stream độc lập ở tầng vận chuyển.
- QUIC gộp bắt tay transport + mã hóa: đo thật HTTP/2 cần TCP (~30ms) rồi TLS (~60ms) = 2 RTT tuần tự; QUIC gộp còn 1 RTT (0-RTT khi nối lại), cộng đổi mạng không đứt nhờ connection ID.
- Khám phá qua Alt-Svc, có fallback: site quảng cáo
alt-svc: h3=":443"để client thử h3 rồi lui về h2 nếu UDP bị chặn; h3 lợi nhất trên mạng mất gói, và thường được bật ở CDN/proxy chứ không code tay (curl cần build kèm h3 mới thử được — lab này không có).
Nguồn
- Cloudflare — HTTP/3: the past, the present, and the future và QUIC: https://blog.cloudflare.com/http3-the-past-present-and-future/
- RFC 9114 (HTTP/3) và RFC 9000 (QUIC): https://www.rfc-editor.org/rfc/rfc9114
Phần sau ta xử lý thứ khiến mọi lập trình viên frontend từng phát điên: CORS — vì sao trình duyệt chặn request cross-origin, preflight OPTIONS, và các header Access-Control-*.