Featured image of post CDN: Mô hình tư duy 'Cửa hàng Tiện lợi'

CDN: Mô hình tư duy 'Cửa hàng Tiện lợi'

Tại sao ảnh load ngay với user Mỹ nhưng ì ạch ở Việt Nam? Hướng dẫn chuyên sâu về CDN Edge Node, Cache-Control header và cache busting.

Ảnh sản phẩm của bạn được host trên server ở Frankfurt. User ở Hà Nội click vào web. Cái ảnh đó phải di chuyển vật lý qua 9,000 km cáp quang biển mới hiện ra trên màn hình của họ.

Vật lý là nút cổ chai. Không ai làm ánh sáng đi nhanh hơn được.

Nhưng bạn có thể đưa nội dung đến gần người dùng hơn. Đây chính là CDN.

Đây là Hướng dẫn chuyên sâu về CDN — từ mô hình tư duy đến Cache-Control headers và cache busting.


Phần 1: Nền tảng (Mô hình tư duy)

Origin Server = Nhà máy Chính

Server của bạn ở Frankfurt là Nhà máy Chính. Nó sản xuất mọi thứ: app, ảnh, video, file CSS.

Vấn đề: nhà máy của bạn ở xa. Vận chuyển từ Frankfurt sang Hà Nội tốn thời gian (150–300ms chỉ riêng mạng).

CDN Edge Node = Cửa hàng Tiện lợi Gần nhà

Một CDN (Cloudflare, AWS CloudFront) vận hành hàng trăm Edge Node — server đặt ở các thành phố trên toàn thế giới.

Hãy xem mỗi Edge Node như một cửa hàng 7-Eleven gần nhà. Nó không sản xuất gì cả; nó chỉ nhập và bán các mặt hàng phổ biến từ Nhà máy Chính.

1
2
3
4
5
6
7
8
User tại Hà Nội
CDN Edge (Singapore) ← Đã có bản sao ảnh/assets của bạn
      │ (cách 10ms)
      │   nếu chưa cached ↓
      └──────────────────► Origin Server (Frankfurt)
                           (cách 300ms — chỉ lần đầu tiên!)

Điểm mấu chốt: User đầu tiên ở mỗi khu vực sẽ “đánh” vào origin. Mọi user sau đó trong khu vực đó được phục vụ từ Edge Node gần nhất. Origin chỉ được gọi MỘT LẦN cho mỗi khu vực, mỗi file.


Phần 2: Điều tra (Cái gì nên được Cache?)

Không phải mọi thứ đều nên để CDN cache. Chỉ nội dung tĩnh, ít thay đổi.

Nên cache CDN?Ví dụTại sao
NênẢnh, CSS, JS bundle, Font, VideoFile giống nhau cho mọi user.
NênAPI response công khaiJSON giống nhau cho mọi user.
KhôngTrang cá nhân (/dashboard)Khác nhau theo từng user.
KhôngEndpoint auth (/login)Không được cache!
KhôngDữ liệu realtime (/stock-price)Thay đổi từng giây.

Header Cache-Control

Bạn ra lệnh cho CDN (và trình duyệt) bao lâu thì cache file bằng HTTP response header Cache-Control.

1
Cache-Control: public, max-age=31536000, immutable
  • public: “Các trung gian (CDN) được phép cache cái này.”
  • max-age=31536000: “Cache trong 1 năm (tính bằng giây).”
  • immutable: “File này sẽ KHÔNG BAO GIỜ thay đổi. Đừng bao giờ check lại.”

Quy tắc vàng cho Static Assets: Dùng TTL dài + cache busting qua content hashing.


Phần 3: Chẩn đoán (Cache Busting — “Update của mình sao chưa hiện?”)

Bạn upload ảnh logo.png mới. Nhưng user vẫn thấy ảnh cũ cả tuần vì CDN đã cache nó rồi.

Đây là nỗi đau số 1 khi dùng CDN. Giải pháp là Cache Busting.

Cách sai (Purge thủ công)

Mỗi lần deploy, bạn vào Cloudflare và bấm “Purge Cache”. Cách này:

  • Dễ quên.
  • Chỉ xóa CDN; trình duyệt của user vẫn có thể còn cache.

Cách đúng (Content Hashing)

Đặt tên file kèm với hash của nội dung. Nội dung thay đổi thì tên file thay đổi. Cache tự động bị vô hiệu hóa.

1
2
3
4
5
# File cũ:
logo.abc123.png   Cache-Control: max-age=31536000

# Bạn cập nhật logo. Build tool phát hiện thay đổi.
logo.def456.png   URL MỚI! CDN & trình duyệt xem đây  file HOÀN TOÀN MỚI.

Các build tool hiện đại (Vite, Webpack) tự làm điều này. <img src="logo.abc123.png" /> sẽ tự trở thành <img src="logo.def456.png" /> sau mỗi lần build có thay đổi file.


Phần 4: Giải pháp (Các pattern cài đặt)

1. Cloudflare (Đơn giản nhất)

Chuyển DNS sang Cloudflare. Mọi HTTP request tự động đi qua mạng lưới toàn cầu của họ. Tài sản tĩnh được cache ở edge.

Mẹo: Đặt Page Rule để cache mọi thứ với TTL dài cho đường dẫn static assets.

2. AWS CloudFront + S3

Host static assets trên S3. Đặt CloudFront phía trước.

1
User → CloudFront (Edge) → S3 (Origin)

Header Cache-Control đúng khi upload lên S3:

1
Cache-Control: public, max-age=31536000

3. Nginx làm “CDN mini” cho origin

Cache response ngay tại Nginx trước khi request chạm đến app:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
proxy_cache_path /tmp/nginx_cache levels=1:2
                 keys_zone=my_cache:10m max_size=1g;

server {
    location /static/ {
        proxy_cache        my_cache;
        proxy_cache_valid  200 1y;    # Cache response 200 trong 1 năm
        add_header         X-Cache-Status $upstream_cache_status;  # HIT hoặc MISS
        proxy_pass         http://backend;
    }
}

Mô hình tư duy chốt hạ

1
2
3
4
5
6
7
CDN Edge Node -> Cửa hàng tiện lợi gần nhà. (Gần, nhanh, có đồ phổ biến).
Origin Server -> Nhà máy chính. (Xa, chính xác, ít khi cần đến).

Cache-Control: max-age=31536000 -> "Giữ cái này đúng 1 năm."
Content Hashing (logo.abc123.png) -> "Tên file mới = cache tự bị vô hiệu hóa."
X-Cache-Status: HIT  -> "Phục vụ từ Edge. User vui."
X-Cache-Status: MISS -> "Phục vụ từ Origin. User chờ."

Quy tắc:

  • Nếu file như nhau cho mọi user → đưa lên CDN.
  • Nếu file thay đổi → dùng content hashing thay vì purge tay.
  • Nếu file là dữ liệu riêng tư → đừng bao giờ để CDN cache.
Được tạo với sự lười biếng tình yêu 🦥

Subscribe to My Newsletter