nginx 缓存命中策略依赖响应头、proxy_cache 配置与 cdn 规则协同:1. 用 add_header 设置 cache-control(如 immutable)控制客户端/cdn 缓存;2. 配置 proxy_cache_path 和 proxy_cache 提升源站 hit 率;3. 通过 $upstream_cache_status 日志分析真实命中状态;4. cdn 必须同步遵循源站 ttl 并规范 cache key。

Nginx 本身不直接提供“缓存命中策略”这种抽象概念,它实际通过缓存控制响应头 + 本地 proxy_cache 配置 + CDN 协同规则共同实现对静态资源“是否缓存、缓多久、是否复用”的精准控制。所谓“命中策略”,本质是让请求尽可能走 HIT(缓存命中),避免 MISS(未命中)或 BYPASS(被绕过)。关键不在“策略开关”,而在三处配置必须协同生效。
1. 响应头明确告诉客户端和 CDN “可缓、长期、不可变”
浏览器和 CDN 是否缓存、缓多久,首要依据是 Nginx 返回的 Cache-Control 头。仅靠 expires 不够精准,推荐统一用 add_header:
- 对带哈希名的 JS/CSS/图片/字体(如
app.a1b2c3.js):add_header Cache-Control "public, max-age=31536000, immutable";
immutable 表示内容永不变,浏览器和 CDN 可跳过协商验证(如 If-None-Match),大幅提升 HIT 率。 - 对 HTML 或动态生成页:
add_header Cache-Control "no-cache, must-revalidate";
禁止缓存,避免页面更新延迟。 - 务必检查 location 优先级 —— 若存在
location ^~ /static这类前缀匹配,它会优先于正则location ~ \.js$生效,导致缓存头根本没加上。可用nginx -T查看最终生效配置。
2. 启用 Nginx 本地磁盘缓存(proxy_cache)减少回源压力
即使 CDN 节点 MISS,多个边缘节点同时回源会冲击源站。加一层 Nginx 本地缓存,能将首次请求后的响应存到磁盘,后续同类请求直接返回,显著提升源站 HIT 率:
- 在
http块定义缓存区:proxy_cache_path /var/cache/nginx/static_cache levels=1:2 keys_zone=static_cache:10m max_size=2g inactive=30d use_temp_path=off; - 在静态资源 location 中启用(注意:必须配合
proxy_pass,不能直接用于root或alias):
推荐用命名 location 模拟代理:location ~* \.(js|css|png|jpg|woff2)$ {<br> proxy_pass http://localhost:@static;<br> proxy_cache static_cache;<br> proxy_cache_valid 200 302 7d;<br> proxy_cache_key "$scheme$request_method$host$request_uri";<br> add_header X-Cache-Status $upstream_cache_status;<br> }<br> location @static {<br> internal;<br> root /data/www;<br> } - 加上
add_header X-Cache-Status $upstream_cache_status;,日志里就能看到 HIT/MISS/BYPASS,方便定位问题。
3. 用日志驱动优化,而不是凭感觉调
缓存是否真命中,不能只看配置,要看真实请求流转。核心是分析 $upstream_cache_status 字段:
- 在 log_format 中显式记录:
log_format cache_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $upstream_cache_status';
并在 location 中启用:access_log /var/log/nginx/static.log cache_log; - 高频问题一眼定位:
awk '{print $12}' /var/log/nginx/static.log | sort | uniq -c | sort -nr
若BYPASS占比高,说明请求被规则主动跳过(比如带 Cookie、Authorization 或非 GET/HEAD 方法);
若MISS集中在特定 URI,大概率是 URL 带随机参数(?v=123)或大小写不一致,需清洗proxy_cache_key(例如去掉$args)。
4. CDN 层必须同步设置,否则 Nginx 头无效
Nginx 发了 max-age=1y,CDN 却可能按自己默认 TTL(比如 1 小时)截断。必须登录 CDN 控制台手动配置:
- .js/.css/.woff2/.png 等带哈希资源:TTL 设为 30 天或勾选“遵循源站”
- .html 文件:TTL 设为 0 或 10 分钟,防止页面更新不生效
- 确认 Cache Key 包含 Host + URI(不含 Cookie、UA 等),避免跨子域缓存污染
- 前端构建输出的资源 URL 必须指向 CDN 域名(如
https://cdn.example.com/app.js),否则请求根本不会经过 CDN。
不复杂但容易忽略











