缓存未命中(MISS)是请求未进入缓存池,主因包括路径权限错误、响应头被忽略、缓存键污染或绕过规则误触发;需正确定义proxy_cache_path于http块、设好目录权限与参数、匹配状态码、忽略干扰响应头、精简cache_key、清理bypass字段,并通过X-Cache-Status和日志验证命中情况。

缓存未命中(MISS)不是配置没写,而是请求根本没进缓存池——常见原因包括路径权限不对、响应头被忽略、缓存键污染或绕过规则误触发。解决核心是让该缓存的请求真正落地、命中、复用。
确保缓存区已正确定义且可写
proxy_cache_path 必须放在 http 块最外层,不能嵌套在 server 或 location 里:
- 提前创建目录并赋权:
sudo mkdir -p /var/cache/nginx/my_cache && sudo chown nginx:nginx /var/cache/nginx/my_cache - 关键参数别漏:
proxy_cache_path /var/cache/nginx/my_cache levels=1:2 keys_zone=my_cache:10m max_size=2g inactive=30m use_temp_path=off;
其中keys_zone是内存索引区(10MB 约支持 8 万个 key),max_size才是磁盘上限 - 检查 proxy_temp_path 是否与缓存路径同文件系统,否则写缓存会失败(报错 Permission denied 或 ERR_CONTENT_LENGTH_MISMATCH)
让缓存真正生效:匹配状态码 + 覆盖干扰头
proxy_cache_valid 不生效,90% 是因为上游返回的状态码或响应头不匹配:
- 先用
curl -I https://your-api/endpoint看真实状态码(可能是 201、206、304,而非默认的 200) - 显式列出所有需缓存的状态码:
proxy_cache_valid 200 201 206 301 302 404 10m; - 上游若返回
Cache-Control: no-cache或max-age=0,Nginx 默认跳过缓存——加proxy_ignore_headers Cache-Control Expires Set-Cookie;强制走自己的规则 - 对静态资源(JS/CSS/图片),建议设长时效:
proxy_cache_valid 200 24h;;对 HTML 或动态接口,用短时效+验证:proxy_cache_valid 200 300s;
避免缓存键污染和绕过
同一个资源生成多个 cache key,等于缓存失效;带 Cookie 或随机参数的请求默认被 bypass:
- 精简 cache_key:
proxy_cache_key "$scheme$host$uri$is_args$args";→ 改为proxy_cache_key "$scheme$host$uri";(去掉 $args,避免 ?t=123456 类参数干扰) - 清理无关请求头:
proxy_cache_bypass $arg_nocache $http_pragma $http_authorization;,再配合proxy_ignore_headers Set-Cookie;防止后端 Set-Cookie 导致 bypass - 若业务需区分用户,就别缓存;若只是公共内容,务必从 key 和 bypass 规则中剔除 $cookie_xxx、$http_x_forwarded_for 等易变字段
验证命中与兜底防击穿
光配不验,等于没配。必须从响应头和日志双向确认:
- 在 location 中加:
add_header X-Cache-Status $upstream_cache_status;,用 curl 查看是否返回X-Cache-Status: HIT - 启用日志变量:
log_format cache '$remote_addr [$time_local] $upstream_cache_status "$request" $status $body_bytes_sent';,观察 access.log 中 HIT/MISS/EXPIRED/BYPASS 分布 - 对高并发场景,开启柔性兜底:
proxy_cache_use_stale error timeout updating http_500;,后端挂了也能返回旧缓存;再加proxy_cache_lock on;限制并发回源数


















