Điều gì xảy ra khi bạn gõ google.com và nhấn Enter?
Trace toàn bộ vòng đời một HTTP request qua 5 chặng — DNS, TCP handshake, TLS, HTTP, render. Bài xương sống của cả khoá: mỗi chặng sẽ có một module riêng đào sâu. Hiểu được vì sao lần load đầu chậm, lần sau nhanh, và mỗi tầng cache ở đâu.
Bạn gõ google.com, nhấn Enter. Khoảng 200ms sau, trang hiện ra. Cảm giác như tức thì — như thể trình duyệt "biết" Google ở đâu và gọi thẳng tới.
Thực tế giữa lúc nhấn Enter và lúc pixel đầu tiên xuất hiện, có 5 chặng riêng biệt chạy qua nhiều máy ở nhiều nơi trên thế giới. Mỗi chặng giải quyết một bài toán khác nhau: máy đó ở địa chỉ nào? làm sao mở được kênh tới nó? làm sao kênh đó an toàn? gửi yêu cầu gì? nhận về rồi vẽ ra sao?
Một backend dev không cần thuộc lòng 7 tầng OSI. Nhưng khi production ném ECONNRESET, khi trang chậm 3 giây không rõ lý do, khi cert hết hạn — bạn cần biết request đang kẹt ở chặng nào. Bài này dựng bản đồ toàn cảnh đó.
Đây là bài xương sống của cả khoá. Mỗi chặng dưới đây sẽ có một module riêng đào sâu: DNS, TCP/IP, HTTP, TLS. Giờ ta đi một vòng nhanh để thấy chúng ráp vào nhau thế nào.
1. Analogy — Gọi điện đến một tổng đài công ty
Hình dung bạn muốn gọi cho một tập đoàn lớn mà chỉ biết tên, không biết số:
- Bạn tra danh bạ để tìm số điện thoại từ tên công ty.
- Bạn quay số, chờ tổng đài nhấc máy, hai bên "alo, nghe rõ không?" để chắc chắn đường dây thông.
- Vì nội dung nhạy cảm, hai bên chuyển sang đường dây mã hoá và thống nhất một bộ mật mã.
- Bạn nói yêu cầu ("cho tôi gặp phòng kinh doanh"), nhận lại câu trả lời.
- Bạn ghi lại và xử lý thông tin nhận được.
Một HTTP request đi đúng 5 bước đó:
| Gọi điện | Networking | Chặng |
|---|---|---|
| Tra danh bạ tìm số | DNS phân giải tên miền ra IP | 1 |
| Quay số, xác nhận đường dây | TCP 3-way handshake | 2 |
| Chuyển sang đường mã hoá | TLS handshake (HTTPS) | 3 |
| Nói yêu cầu, nghe trả lời | HTTP request / response | 4 |
| Ghi lại, xử lý | Browser parse và render | 5 |
Một request luôn đi theo thứ tự: địa chỉ → kết nối → bảo mật → nội dung → hiển thị. Lỗi ở chặng sớm (DNS) thì các chặng sau không bao giờ chạy.
2. Toàn cảnh 5 chặng
Toàn bộ câu chuyện chỉ có ba nhân vật chính: trình duyệt của bạn, hệ thống DNS, và server đích.
Đây là sequence diagram của một lần load https://google.com từ con số 0 (chưa cache gì):
sequenceDiagram
participant B as Browser
participant D as DNS Resolver
participant S as Server (google.com)
B->>D: google.com co IP nao?
D-->>B: 142.250.x.x
Note over B,S: Chang 1 — DNS (~20-120ms)
B->>S: SYN
S-->>B: SYN-ACK
B->>S: ACK
Note over B,S: Chang 2 — TCP handshake (1 RTT)
B->>S: ClientHello
S-->>B: ServerHello + cert
B->>S: Finished
Note over B,S: Chang 3 — TLS handshake (1 RTT, TLS 1.3)
B->>S: GET / HTTP/2
S-->>B: 200 OK + HTML
Note over B,S: Chang 4 — HTTP request/response
Note over B: Chang 5 — parse HTML, tai CSS/JS, renderĐiểm mấu chốt: mỗi mũi tên qua lại là một lần đi vòng mạng — gọi là RTT (Round-Trip Time), thời gian gói tin đi tới server và quay về. RTT trong nước cỡ 10-30ms, đi quốc tế có thể 150-300ms. Càng nhiều chặng nối tiếp, độ trễ càng cộng dồn. Đây là lý do tối ưu mạng phần lớn là giảm số RTT, không phải tăng băng thông.
3. Chặng 1 — DNS: tên miền thành địa chỉ IP
Máy tính không định tuyến theo tên google.com — chúng định tuyến theo địa chỉ IP (ví dụ 142.250.190.78). DNS (Domain Name System) là hệ thống tra cứu biến tên thành IP.
Bạn tự chạy thử bằng dig:
dig google.com +short
# 142.250.190.78
Trình duyệt không hỏi thẳng "tổng đài gốc" mỗi lần. Nó tra qua một chuỗi cache:
flowchart LR
A[Browser cache] --> B[OS cache]
B --> C[Router]
C --> D[ISP resolver]
D --> E[Root / TLD / Authoritative]Hỏi tới đâu thấy kết quả còn hạn (TTL chưa hết) thì dừng. Lần đầu vào một domain lạ có thể mất 100ms+ vì phải đi tới cuối chuỗi; lần sau gần như 0ms vì đã cache. Đây là chặng đầu tiên có thể làm trang "đơ" vài giây nếu resolver chậm — và là thủ phạm hay bị bỏ qua khi debug.
Mỗi bản ghi DNS có TTL (Time To Live) — số giây được phép cache. Đặt TTL 3600 nghĩa là sau khi đổi IP, vẫn có client dùng IP cũ tới một giờ vì họ còn bản cache. Trước khi chuyển server, người ta thường hạ TTL xuống trước vài ngày.
4. Chặng 2 — TCP handshake: bắt tay 3 bước
Có IP rồi, nhưng chưa thể gửi dữ liệu ngay. Hai đầu — client và server — phải bắt tay mở kết nối trước.
TCP cần thiết lập kết nối trước qua 3 gói tin — gọi là 3-way handshake:
sequenceDiagram
participant B as Client
participant S as Server
B->>S: SYN (toi muon ket noi, seq=x)
S-->>B: SYN-ACK (ok, seq=y, ack=x+1)
B->>S: ACK (xac nhan, ack=y+1)
Note over B,S: Ket noi mo — san sang truyen du lieuBa bước này để cả hai phía đồng ý mở kết nối và đồng bộ số thứ tự gói (sequence number) dùng cho việc đảm bảo dữ liệu tới đủ và đúng thứ tự sau này. Tốn đúng 1 RTT trước khi byte dữ liệu đầu tiên được gửi.
Vì sao một backend dev phải quan tâm? Vì handshake này tốn tài nguyên ở server, và khi đóng kết nối lại sinh ra trạng thái TIME_WAIT — nguồn cơn của lỗi "hết port" kinh điển trên server tải cao (sẽ có hẳn một bài ở module TCP). Bạn xem trạng thái các kết nối bằng:
ss -tan | head
# State Recv-Q Send-Q Local Address:Port Peer Address:Port
# ESTAB 0 0 10.0.0.5:443 203.0.113.7:51324
# TIME-WAIT 0 0 10.0.0.5:443 203.0.113.7:51210
5. Chặng 3 — TLS: thiết lập kênh mã hoá
URL bắt đầu bằng https nghĩa là dữ liệu phải được mã hoá. Sau khi TCP mở kết nối, hai bên chạy thêm TLS handshake: trao đổi để (1) xác thực server đúng là google.com qua certificate, và (2) thống nhất một khoá mã hoá chung cho phiên này.
Với TLS 1.3, handshake tốn thêm 1 RTT (TLS 1.2 tốn 2 RTT — đây là một lý do nâng cấp TLS giúp web nhanh hơn). Bạn quan sát toàn bộ chặng 1→3→4 chỉ bằng một lệnh curl:
curl -v https://google.com -o /dev/null
# * Connected to google.com (142.250.190.78) port 443 <- DNS + TCP xong
# * TLS handshake, Done <- TLS xong
# > GET / HTTP/2 <- chang 4 bat dau
# < HTTP/2 200
Cờ -v (verbose) in từng chặng. Khi gặp lỗi cert hết hạn hay "Not Secure", chặng dừng ngay ở dòng TLS — và curl -v cho bạn thấy chính xác nó hỏng ở đâu.
TLS giải quyết ba việc cùng lúc: mã hoá (người khác không đọc được), toàn vẹn (không bị sửa giữa đường), và xác thực (đúng server bạn nghĩ, không phải kẻ giả mạo). Thiếu xác thực thì mã hoá vô nghĩa — bạn có thể đang trao đổi mật mã an toàn với kẻ tấn công.
6. Chặng 4 — HTTP: request và response
Đến đây kênh đã mở và an toàn. Trình duyệt mới gửi HTTP request thật sự — yêu cầu nội dung. Một request tối giản:
GET / HTTP/2
Host: google.com
User-Agent: Mozilla/5.0 ...
Accept: text/html
Server trả về response:
HTTP/2 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: private, max-age=0
<!DOCTYPE html>...
Dòng đầu response chứa status code — 200 là OK, 404 không tìm thấy, 500 server lỗi, 301 chuyển hướng. Phần lớn công việc đọc lỗi production của backend dev nằm ở việc hiểu đúng status code và header. Đây là tầng bạn "sống cùng" mỗi ngày, nên cả một module sẽ dành riêng cho nó.
7. Chặng 5 — Browser render (tóm tắt)
Nhận được HTML, trình duyệt parse ra cây DOM, phát hiện cần thêm CSS, JS, ảnh — và lặp lại chặng 1-4 cho từng tài nguyên đó. Một trang thường kéo hàng chục request con. Đây là lý do HTTP/2 (multiplexing nhiều request trên một kết nối) tạo khác biệt lớn về tốc độ so với HTTP/1.1.
Chặng render thuộc về frontend nhiều hơn, nên khoá này chỉ điểm qua — trọng tâm của ta là 4 chặng mạng phía trước.
8. Vì sao lần đầu chậm, lần sau nhanh
Ghép lại, ngân sách độ trễ một lần load "nguội" (chưa cache) trông như sau:
| Chặng | Lần đầu (nguội) | Lần sau (ấm) |
|---|---|---|
| DNS | 20-120ms | ~0 (đã cache) |
| TCP handshake | 1 RTT | 0 (tái dùng kết nối keep-alive) |
| TLS handshake | 1 RTT | 0 (session resumption) |
| HTTP | thời gian server xử lý | thường ~0 nếu cache HTTP |
Gần như mọi tầng đều có cache riêng. Đây là insight quan trọng nhất bài này: tối ưu hiệu năng mạng phần lớn là tránh làm lại chặng đã làm — tái dùng kết nối TCP, resume phiên TLS, cache DNS, cache HTTP. Mỗi cache bạn bỏ lỡ là một RTT cộng thêm vào độ trễ người dùng cảm nhận.
9. Pitfall — hiểu nhầm thường gặp
❌ Nhầm 1: "Trang chậm chắc do server yếu / cần thêm CPU."
✅ Server có thể trả byte đầu tiên trong 5ms, nhưng nếu DNS resolver chậm 2 giây hoặc TLS handshake đi vòng quốc tế, người dùng vẫn chờ 2 giây. Luôn xác định chặng nào chậm trước khi tối ưu — curl -w in được thời gian từng chặng.
❌ Nhầm 2: "HTTPS chỉ làm chậm vì phải mã hoá." ✅ Chi phí mã hoá dữ liệu là không đáng kể trên CPU hiện đại. Chi phí thật của HTTPS là handshake (thêm RTT) — và nó được loại bỏ gần hết nhờ keep-alive và session resumption. Đổi lại, HTTP/2 (chỉ chạy trên HTTPS) thường làm trang nhanh hơn HTTP thuần.
❌ Nhầm 3: "ping được thì mạng ổn, lỗi phải do code."
✅ ping chỉ kiểm tra chặng định tuyến IP (ICMP), không đụng tới TCP/TLS/HTTP. Ping thông mà app vẫn timeout là chuyện thường — vì lỗi nằm ở port bị firewall chặn, TLS sai cert, hay server không listen. Mỗi chặng phải debug bằng công cụ của chặng đó.
10. 📚 Deep Dive — tài liệu gốc
Đọc khi muốn đi tới tận gốc từng chặng:
- RFC 1034 / 1035 — DNS — định nghĩa gốc hệ thống tên miền và cơ chế phân giải.
- RFC 9293 — TCP — bản hợp nhất mới nhất của giao thức TCP, gồm 3-way handshake và quản lý kết nối.
- RFC 8446 — TLS 1.3 — handshake 1-RTT, lý do nhanh hơn TLS 1.2.
- RFC 9110 — HTTP Semantics — ngữ nghĩa method, status code, header dùng chung cho mọi phiên bản HTTP.
Ghi chú: Không cần đọc hết RFC để làm việc — chúng là tài liệu tra cứu chuẩn xác khi có tranh cãi "spec nói gì". Mỗi module sau sẽ trích đúng phần liên quan của các RFC này.
11. Tóm tắt
- Một HTTP request đi qua 5 chặng nối tiếp: DNS → TCP → TLS → HTTP → render. Lỗi ở chặng sớm chặn mọi chặng sau.
- DNS biến tên miền thành IP, tra qua một chuỗi cache; TTL quyết định bao lâu kết quả còn được dùng lại.
- TCP 3-way handshake (SYN / SYN-ACK / ACK) mở kết nối và đồng bộ sequence number, tốn 1 RTT.
- TLS handshake thiết lập kênh mã hoá + xác thực server; TLS 1.3 chỉ tốn 1 RTT.
- HTTP là tầng request/response thật — status code và header là nơi backend dev đọc lỗi nhiều nhất.
- Mỗi RTT là một lần đi-về mạng; tối ưu hiệu năng chủ yếu là giảm số RTT chứ không phải tăng băng thông.
- Gần như mọi tầng đều có cache — lần load "ấm" bỏ qua phần lớn handshake nhờ keep-alive và session resumption.
- Khi debug, xác định chặng nào hỏng trước (
curl -v,dig,ss), rồi mới dùng công cụ của đúng chặng đó.
12. Tự kiểm tra
Q1Vì sao lần đầu vào một website thường chậm hơn rõ rệt so với những lần sau, dù server không đổi gì?▸
Q2Một backend dev nói: 'tôi ping server thấy thông, nên lỗi timeout của app chắc chắn do code'. Lập luận này sai ở đâu?▸
ping chỉ kiểm tra chặng định tuyến IP qua giao thức ICMP — nó không mở TCP, không chạy TLS, không gửi HTTP. Ping thông chỉ chứng minh gói tin tới được máy và quay về, không chứng minh port đang mở, cert còn hạn, hay server đang listen. App vẫn có thể timeout vì firewall chặn port, TLS sai cert, hoặc service chưa khởi động. Mỗi chặng phải debug bằng công cụ của chặng đó.Q3Vì sao người ta thường nói tối ưu tốc độ mạng là 'giảm số RTT' chứ không phải 'tăng băng thông'?▸
Q4TLS giải quyết ba vấn đề, không chỉ một. Đó là ba vấn đề gì, và vì sao thiếu phần xác thực thì mã hoá trở nên vô nghĩa?▸
TLS đảm bảo cùng lúc:
- Mã hoá (confidentiality): người ngoài không đọc được nội dung.
- Toàn vẹn (integrity): dữ liệu không bị sửa giữa đường.
- Xác thực (authentication): server đúng là bên bạn nghĩ, qua certificate.
Thiếu xác thực, bạn có thể thiết lập một kênh mã hoá hoàn hảo — nhưng với kẻ tấn công đứng giữa. Mã hoá an toàn tới đâu cũng vô nghĩa nếu bạn đang trao đổi với nhầm đối tượng.
Q5Bạn đổi server sang IP mới, sửa bản ghi DNS xong nhưng nhiều người dùng vẫn vào IP cũ suốt nhiều giờ. Cơ chế nào gây ra, và cách phòng trước là gì?▸
Q6Khi một trang load chậm 3 giây, vì sao 'nâng cấp CPU server' có thể hoàn toàn không giúp gì?▸
curl -w in thời gian DNS, connect, TLS, time-to-first-byte) để biết nút thắt thật nằm ở đâu rồi mới tối ưu đúng chỗ.Bài tiếp theo: DNS — phân giải tên miền hoạt động thế nào
Bài này có giúp bạn hiểu bản chất không?
Hỏi đáp về bài này
Chưa có câu hỏi
Có gì chưa rõ trong bài? Đặt câu hỏi đầu tiên — câu trả lời từ cộng đồng giúp bạn (và người sau).
Đặt câu hỏi đầu tiên