System Design

Vì sao request đầu tiên luôn chậm hơn? TCP handshake “ăn” mất 1 RTT

Tóm tắt

Trước khi gửi byte dữ liệu đầu tiên, client và server phải bắt tay TCP, tốn trọn một vòng đi-về (RTT). Các request tiếp theo đi lại trên kết nối cũ (keep-alive) nên nhanh hơn đúng 1 RTT.

Dòng thời gian với RTT = 80ms

MốcSự kiện
0 → 40msClient gửi SYN sang server.
40 → 80msServer đáp SYN-ACK (ack = seq của SYN + 1).
80msClient gửi ACK kèm luôn GET / — byte dữ liệu đầu tiên mới rời máy.
160msResponse của request đầu tiên về tới client.
+80msRequest thứ hai (GET /app.js) đi trên kết nối cũ: chỉ cần 1 RTT.

Áp dụng thế nào?

  • Tái sử dụng kết nối: Bật keep-alive và connection pooling (HTTP client, DB driver) để tránh bắt tay lặp lại.
  • Frontend: Dùng <link rel="preconnect"> cho domain quan trọng (font, API, CDN) để bắt tay sớm.
  • Hạ tầng: HTTP/2 gộp nhiều request trên một kết nối; HTTP/3 (QUIC) gộp bắt tay transport và TLS để giảm số RTT. Đưa server lại gần user (CDN/edge) để rút ngắn chính RTT.
  • Khi đo hiệu năng: Tách riêng thời gian kết nối khỏi thời gian xử lý của server để không đổ oan cho backend.