Vấn đề "Luôn MISS" gây ức chế
Bạn đã dành thời gian cấu hình proxy_cache_path và ánh xạ các zone của mình. Bạn chạy lệnh curl, mong đợi phản hồi cực nhanh trong 5ms, nhưng các header vẫn ngoan cố hiển thị MISS. Ngay cả sau khi tải lại mười lần, thư mục cache trên đĩa của bạn vẫn trống rỗng và TTFB (Time to First Byte) của backend vẫn chậm chạp ở mức 200ms hoặc cao hơn.
X-Cache-Status: MISS
Điều này xảy ra vì Nginx được thiết kế để "an toàn" theo mặc định. Nó thà làm chậm trang web của bạn còn hơn là vô tình cung cấp dữ liệu phiên riêng tư của người dùng này cho khách truy cập khác.
Nguyên nhân gốc rễ: Nginx đang quá thận trọng
Nginx tuân thủ nghiêm ngặt các tiêu chuẩn HTTP caching. Nếu backend của bạn (Node.js, Laravel, Django, v.v.) gửi các header ám chỉ một phiên duy nhất, Nginx sẽ từ chối lưu trữ phản hồi. Ba thủ phạm phổ biến nhất là:
- Set-Cookie: Nếu ứng dụng của bạn gửi
PHPSESSIDhoặcconnect.sid, Nginx giả định trang đó đã được cá nhân hóa. - Authorization: Nếu yêu cầu bao gồm Bearer token hoặc Basic Auth, Nginx coi phản hồi đó là riêng tư.
- Cache-Control: Các header như
no-cache,no-store, hoặcprivateyêu cầu Nginx một cách rõ ràng là không được can thiệp.
Khi Nginx thấy những header này, nó mặc định chuyển sang MISS để ngăn rò rỉ dữ liệu nhạy cảm. Để khắc phục, bạn phải chỉ định rõ ràng cho Nginx biết những header nào cần bỏ qua.
Cách khắc phục: Ghi đè logic Header mặc định
Chỉ thị proxy_ignore_headers là công cụ chính của bạn ở đây. Nó yêu cầu Nginx bỏ qua các hướng dẫn cụ thể từ backend và vẫn tiến hành lưu cache nội dung.
Bước 1: Cập nhật cấu hình Nginx của bạn
Mở cấu hình trang web của bạn (thường ở /etc/nginx/sites-available/) và sửa đổi block location. Thêm các dòng này sẽ buộc Nginx lưu cache ngay cả khi có cookie:
location / {
proxy_pass http://backend_upstream;
proxy_cache my_cache_zone;
# Yêu cầu Nginx bỏ qua các header này từ backend
proxy_ignore_headers Set-Cookie Cache-Control Expires;
# Ẩn header Set-Cookie khỏi người dùng cuối để ngăn rò rỉ phiên (session bleeding)
proxy_hide_header Set-Cookie;
# Lưu cache các phản hồi 200 thành công trong 60 phút
proxy_cache_valid 200 60m;
# Header để gỡ lỗi
add_header X-Cache-Status $upstream_cache_status;
}
Bước 2: Xử lý các yêu cầu có xác thực
Nếu API của bạn sử dụng header Authorization nhưng cung cấp cùng một dữ liệu cho mọi người (như danh sách sản phẩm công khai), Nginx vẫn sẽ bỏ qua cache. Để vượt qua điều này, hãy bật proxy_cache_allow_authentication:
location /api/public {
proxy_cache my_cache_zone;
proxy_cache_allow_authentication on;
proxy_ignore_headers Cache-Control;
proxy_cache_valid 200 10m;
}
Bước 3: Kiểm tra và Tải lại
Trước khi áp dụng các thay đổi, hãy xác minh cú pháp của bạn. Một dấu chấm phẩy bị thiếu cũng có thể làm hỏng máy chủ web.
sudo nginx -t
sudo systemctl reload nginx
Xác minh: Xác nhận trạng thái HIT
Sử dụng curl để kiểm tra các header. Yêu cầu đầu tiên có khả năng sẽ là MISS khi Nginx lấy dữ liệu và ghi vào đĩa. Yêu cầu thứ hai sẽ là HIT.
curl -I https://yourdomain.com/api/data
Tìm các dòng cụ thể sau:
HTTP/1.1 200 OK
...
X-Cache-Status: HIT
...
Nếu bạn vẫn thấy MISS, hãy đảm bảo thư mục proxy_cache_path của bạn có quyền ghi cho người dùng www-data hoặc nginx. Bạn có thể kiểm tra việc này bằng lệnh ls -ld /var/cache/nginx.
An toàn là trên hết: Các thực hành tốt nhất
Buộc lưu cache là một kỹ thuật mạnh mẽ nhưng đi kèm rủi ro. Hãy tuân thủ các quy tắc sau để tránh cung cấp dữ liệu riêng tư cho nhầm người:
- Cô lập các đường dẫn nhạy cảm: Không bao giờ sử dụng
proxy_ignore_headers Set-Cookietrên các trang/admin,/checkout, hoặc/settings. - Sử dụng Cache Bypassing: Triển khai
proxy_cache_bypass $cookie_nocache. Điều này cho phép bạn cung cấp nội dung đã lưu cache cho khách trong khi vẫn cung cấp dữ liệu mới, được cá nhân hóa cho người dùng đã đăng nhập. - Loại bỏ Cookie: Luôn sử dụng
proxy_hide_header Set-Cookiekhi bỏ qua cookie để đảm bảo trình duyệt không lưu trữ ID phiên cũ từ cache.

