浏览器缓存与nginx代理缓存是协同而非互斥的两级缓存:浏览器在客户端本地缓存资源以减少请求,nginx在服务端缓存后端响应以降低源站压力;二者需通过统一cache_key、对齐cache-control头(如immutable/304验证)、分层配置(静态资源强缓存、html校验、api分级proxy_cache_valid)实现高效配合。

浏览器缓存和 Nginx 代理缓存不是互斥关系,而是天然协同的两级缓存:浏览器在用户本地“最后一公里”缓存资源,Nginx 在服务端入口处统一缓存后端响应。两者配合得当,能显著降低源站压力、提升首屏加载速度,并增强系统容错能力。
浏览器缓存:控制客户端是否发请求
它决定用户访问时是否跳过网络请求,直接读取本地副本。关键靠响应头控制:
-
静态资源(带哈希文件名):用
Cache-Control: public, max-age=31536000, immutable,让浏览器一年内不验证、不重发请求 -
普通静态资源(CSS/JS/图片):设
max-age=2592000(30天),允许 CDN 和浏览器共用 -
HTML 入口文件:用
private, no-cache, must-revalidate,强制每次访问都向 Nginx 验证,避免白屏或旧版页面
注意:这些头必须通过 add_header ... always 设置,否则 304 响应不会携带缓存头,导致后续请求降级为无缓存。
Nginx 代理缓存:拦截并复用上游响应
当浏览器发起验证请求(如带 If-None-Match),Nginx 可以不打后端,直接返回 304;若请求未命中浏览器缓存,Nginx 就用自己的 proxy_cache 挡住重复请求:
- 在
http块中定义缓存区:proxy_cache_path /var/cache/nginx/api_cache levels=1:2 keys_zone=api_cache:64m use_temp_path=off; - 在
location中按需启用:proxy_cache api_cache;,只对/api/或静态正则路径开启 - 分级设置有效期:
proxy_cache_valid 200 302 12h;,proxy_cache_valid 404 1m;,避免错误响应长期滞留 - 允许绕过缓存:
proxy_cache_bypass $http_cache_control;,支持客户端发Cache-Control: no-cache强制回源
缓存键设计:打通两级缓存一致性
如果浏览器缓存的资源和 Nginx 缓存的资源使用不同 key,就会出现“浏览器有缓存但 Nginx 没缓存”,或“Nginx 缓存了却因参数乱码被浏览器丢弃”的情况。关键点:
- 浏览器侧依赖
$request_uri(含 query string)生成 ETag 或 Last-Modified,所以 Nginx 的proxy_cache_key应尽量对齐,例如:"$scheme$host$request_uri" - 过滤高变字段:去掉
$arg_utmsource、$http_user_agent、$cookie_sessionid等,防止同一资源被缓存多份 - 多域名共用缓存时保留
$host,避免 example.com 的 JS 覆盖 api.example.com 的接口响应
上线前必须验证真实命中链路
配置写完不等于生效,要逐层确认:
- 浏览器 Network 面板看状态码:200(from memory/disk cache)→ 表明浏览器命中;304 → 表明浏览器验证成功,Nginx 返回了未修改响应
- 检查响应头:
X-Cache-Status(需手动加add_header X-Cache-Status $upstream_cache_status;)显示HIT/MISS/STALE,确认 Nginx 是否真用了缓存 - 日志里加
$upstream_cache_status字段,批量分析缓存效率,比如发现大量BYPASS就说明proxy_cache_bypass条件太宽











