nginx 缓存绕过本身不直接导致缓存穿透,但配置不当会放大风险:请求未抵达缓存层、cache_key不一致致永久miss、协商头丢失或敏感请求误缓存,均使流量直击后端;需通过$upstream_cache_status验证生效、统一透传if-none-match等头、精准设cache_key、启用proxy_cache_lock与proxy_cache_use_stale兜底。

多级网关环境下,Nginx 缓存绕过本身不直接导致缓存穿透,但若配置不当,会放大穿透风险——比如请求根本没走到 Nginx 缓存层,或缓存键设计不合理导致永远 MISS,最终所有流量直击后端。处理核心不是“堵住绕过”,而是确保缓存层真实生效、命中可控、失效可兜底。
确认请求是否真正抵达 Nginx 缓存节点
多层代理(如 CDN → API 网关 → Nginx 边缘缓存 → 后端)中,缓存绕过常是“假象”:前端或中间网关已跳过 Nginx,直连后端。
- 在 Nginx access_log 中启用
$upstream_cache_status变量,观察日志里是否出现HIT/MISS/BYPASS;若大量请求无该字段或全是-,说明请求未进入该 Nginx 实例 - 检查上游网关(如 Kong、Traefik)是否对特定 Header(如
Authorization、Cookie)默认禁用缓存转发,或配置了cache-control: no-cache强制透传 - 用
curl -v追踪完整链路,比对各跳响应头中的X-Cache或自定义标识,定位哪一层丢弃了缓存逻辑
统一透传协商头并加固缓存键
多级转发易剥离 If-None-Match、If-Modified-Since 和 ETag,导致协商缓存失效,重复回源——这会加剧穿透压力。
- 在每层 Nginx 的
location块中显式透传:proxy_set_header If-None-Match $http_if_none_match;和proxy_set_header If-Modified-Since $http_if_modified_since; - 禁用自动忽略:
proxy_ignore_headers ETag;必须删除,否则上游返回的 ETag 被丢弃 - 缓存键必须包含协商头:
proxy_cache_key "$scheme$request_method$host$request_uri$is_args$args$http_if_none_match$http_if_modified_since";,避免相同 URI 不同条件请求复用错误缓存
精准控制绕过行为,防止敏感请求污染缓存
开发调试、管理接口、带身份凭证的请求应绕过缓存,但必须“读写双绕过”,否则响应可能被错误缓存。
- 使用同一变量同时配置:
proxy_cache_bypass $http_x_bypass_cache;和proxy_no_cache $http_x_bypass_cache; - 按路径绕过需用
map预判,例如在http块中定义:map $request_uri $skip_cache { ~*^/admin/|~*\.php$ 1; default 0; },再在 location 中引用 - 避免用易变字段(如
$cookie_sessionid、$arg_t)参与 cache_key,否则缓存粒度失控,等效于永不命中
启用缓存锁与 stale 模式防雪崩式穿透
当热点资源缓存失效瞬间,大量并发请求同时回源,极易击穿后端。Nginx 提供原生机制缓解。
- 开启缓存锁:
proxy_cache_lock on;+proxy_cache_lock_timeout 5s;,确保同一 key 只有一个请求回源,其余等待缓存生成后直接返回 - 允许使用过期缓存应对源站异常:
proxy_cache_use_stale error timeout updating http_502 http_503 http_504; - 为 304 响应单独设置有效期:
proxy_cache_valid 304 24h;,避免每次验证都触发回源











