jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

Web Performance · Part 19 — Network Protocol & Transport Performance

Tầng truyền tải ảnh hưởng tốc độ ra sao: HTTP/1.1 vs HTTP/2 vs HTTP/3 (QUIC), head-of-line blocking, nén Brotli/Zstd, TLS 1.3 & 0-RTT, CDN/edge, và cache-control nâng cao.

Phần 11 bàn caching cơ bản. Phần này đi xuống tầng truyền tải — giao thức HTTP và TCP/QUIC bên dưới mọi request. Đây là phần nhiều frontend dev coi là “hộp đen của ops”, nhưng hiểu nó giải thích vì sao chiến lược bundle thời HTTP/1.1 cần đổi, HTTP/3 giúp gì khi mất gói, và làm sao cấu hình cache cho đúng.

Mỗi byte phải đi qua: DNS → kết nối (TCP/QUIC + TLS) → request → response. Tối ưu tầng này rút ngắn TTFB và mở khóa song song — nền cho mọi tài nguyên phía trên.


1. HTTP/1.1 → HTTP/2: multiplexing

Browser hiện đại thường không dùng HTTP/1.1 pipelining, nên mỗi kết nối chỉ có một request đang phản hồi tại một thời điểm và mở một nhóm kết nối song song (thường khoảng 6, tùy browser/origin). Nhiều file → xếp hàng. Đó là lý do thời HTTP/1.1 ta gộp file, dùng sprite, domain sharding.

HTTP/1.1:  6 kết nối, mỗi cái 1 request một lúc → file thứ 7 phải chờ
HTTP/2:    thường 1 kết nối/origin, MULTIPLEXING nhiều stream song song

HTTP/2 ghép nhiều request/response trên một kết nối qua các stream độc lập. Hệ quả thực tế:

  • Không còn cần bundle khổng lồ, sprite hay domain sharding chỉ để né giới hạn kết nối HTTP/1.1.
  • Có thể chia bundle theo route/feature để caching tốt hơn, nhưng quá nhiều chunk nhỏ vẫn có overhead header, scheduling, nén và parse. Đo để tìm granularity phù hợp.

2. Head-of-line blocking & HTTP/3 (QUIC)

HTTP/2 multiplexing ở tầng HTTP, nhưng vẫn chạy trên TCP. TCP đảm bảo thứ tự byte: nếu một gói tin mất, mọi stream trên kết nối đó phải chờ truyền lại — TCP head-of-line blocking. Trên mạng kém (mobile, mất gói cao), điều này giết hiệu năng dù đã multiplexing.

HTTP/2 trên TCP: gói của stream A mất → stream B, C cũng kẹt chờ (HOL blocking)

HTTP/3 trên QUIC (UDP): mỗi stream độc lập ở tầng truyền tải
   → gói stream A mất CHỈ chặn A; B, C chạy tiếp  ✅

HTTP/3 chạy trên QUIC (trên UDP), loại bỏ TCP HOL giữa các QUIC stream: mất dữ liệu của stream A không buộc B/C chờ retransmit của A. Nó không xóa mọi tác động của mất gói — congestion control vẫn có thể giảm tốc cả connection, và chính stream A vẫn chờ dữ liệu thiếu. QUIC tích hợp TLS và hỗ trợ connection migration, thường hữu ích trên mạng latency/mất gói cao; mức cải thiện phải đo theo người dùng thật.


3. TLS 1.3 & 0-RTT — bắt tay nhanh hơn

Thiết lập kết nối an toàn tốn round-trip. TLS 1.3 giảm bắt tay xuống 1-RTT, và 0-RTT cho phép gửi dữ liệu ngay khi kết nối lại với server đã biết.

TLS 1.2:  2-RTT bắt tay  → chậm hơn
TLS 1.3:  1-RTT          → nhanh hơn
TLS 1.3 + 0-RTT (resumption): 0-RTT cho lần kết nối lại → gửi request ngay
QUIC:     gộp transport + TLS → ít round-trip hơn nữa

Cảnh báo bảo mật 0-RTT: early data có thể bị replay. Chỉ chấp nhận operation được thiết kế replay-safe và có policy/anti-replay phía server; đừng suy rằng mọi GET đều an toàn chỉ vì method được xem là idempotent (một endpoint GET viết sai vẫn có thể tạo side effect).


4. Nén — Brotli & Zstd

Nén giảm byte truyền. Với text (HTML/CSS/JS/JSON), Brotli thường tạo response nhỏ hơn gzip; Zstandard (zstd) có thể cân bằng tốt giữa tốc độ và tỉ lệ. Kết quả phụ thuộc corpus, quality level và CPU — không có một phần trăm đúng cho mọi site.

Hiệu quả nén text (xấp xỉ):
  gzip    → baseline
  Brotli  → thường nhỏ hơn gzip cho asset text tĩnh
  Zstd    → nén/giải nén nhanh ở nhiều mức, support client còn cần kiểm tra
Nguyên tắc:
  - pre-compress asset tĩnh lúc build; chọn quality bằng benchmark, không mặc định mức tối đa
  - nén động cho response sinh-tại-chỗ ở mức vừa (cân CPU)
  - ĐỪNG nén lại thứ đã nén: ảnh (jpg/png/webp/avif), woff2, video, zip
  - Content-Encoding đúng + Vary: Accept-Encoding

Đa số ảnh và woff2 đã nén sẵn — nén lại tốn CPU mà không giảm byte.

Server phải negotiate qua Accept-Encoding và luôn có fallback br/gzip cho client hoặc intermediary chưa hỗ trợ zstd; gửi Vary: Accept-Encoding để cache không trộn các representation.


5. CDN & edge — gần người dùng hơn

CDN đặt nội dung ở edge gần người dùng, cắt latency (khoảng cách vật lý = thời gian). Vai trò hiệu năng:

- phục vụ asset tĩnh từ edge gần nhất → TTFB & LCP thấp
- TLS termination ở edge → bắt tay nhanh hơn
- HTTP/3 + 0-RTT ở edge
- edge cache cho cả HTML động (với cache key/purge đúng)
- edge compute (Workers/Functions) → render/cá nhân hóa gần người dùng

Edge rendering có thể giảm network latency, nhưng không tự động hạ TTFB nếu compute cold-start hoặc vẫn phải gọi database ở một region xa. Đặt cache/compute gần người dùng gần dependency phù hợp, rồi kiểm tra bằng Server-Timing và field TTFB.


6. Cache-Control nâng cao

Header cache quyết định trình duyệt/CDN giữ và tái dùng response thế nào. Vài pattern senior:

Các dòng # dưới đây là chú thích cho từng policy, không phải header gửi trên wire:

# Asset có hash trong tên (app.a1b2c3.js) → bất biến, cache 1 năm
Cache-Control: public, max-age=31536000, immutable

# HTML → luôn revalidate (nội dung có thể đổi)
Cache-Control: no-cache    # = phải kiểm tra với server (ETag) trước khi dùng

# stale-while-revalidate: phục vụ bản cũ NGAY, làm tươi ở nền
Cache-Control: public, max-age=60, stale-while-revalidate=600
Các chỉ thị then chốt:
  immutable               → đừng revalidate trong max-age (asset có hash)
  no-cache ≠ no-store     → no-cache: cache nhưng phải revalidate;
                            no-store: không lưu gì cả
  stale-while-revalidate  → trả stale ngay + cập nhật nền (UX mượt)
  s-maxage / private      → kiểm soát riêng cho CDN vs trình duyệt

Baseline an toàn phổ biến: HTML no-cache (được lưu nhưng phải revalidate) + asset hash immutable 1 năm. Đây không phải policy duy nhất: HTML công khai có thể dùng s-maxage/stale-while-revalidate ở CDN, còn response cá nhân hóa cần private hoặc no-store cùng cache key đúng. Luôn thiết kế purge/invalidation trước khi tăng TTL.


7. Tóm tắt

  • HTTP/2 multiplexing bỏ lý do gộp file chỉ để né connection limit, nhưng quá nhiều chunk nhỏ vẫn có overhead.
  • HTTP/3 (QUIC trên UDP) loại TCP HOL giữa stream; mất gói và congestion vẫn tồn tại, nên lợi ích tùy mạng.
  • TLS 1.3 bắt tay 1-RTT, 0-RTT cho kết nối lại chỉ với operation replay-safe và server policy đúng.
  • Nén Brotli/Zstd cho text với content negotiation + fallback; benchmark quality và đừng nén lại ảnh/woff2/video.
  • CDN/edge cắt latency bằng cách phục vụ gần người dùng (asset tĩnh, TLS, HTTP/3, edge render).
  • Cache-Control: asset hash immutable; HTML chọn no-cache, CDN TTL hay private/no-store theo loại dữ liệu; phân biệt no-cache vs no-store.

Phần tiếp theo: Third-party script performance — chế ngự analytics/ads/embed/tag manager bằng facade pattern, Partytown (đẩy sang worker), lazy iframe và đặt budget cho bên thứ ba.