要精准分析Nginx缓存效果,必须记录并统计$upstream_cache_status六种状态(HIT/MISS/EXPIRED/BYPASS/STALE/UPDATING)的分布,确保日志正确采集、格式定义与作用域匹配,并为关键路径切分结构化日志,辅以调试响应头和shell命令快速诊断。

要真正看清 Nginx 缓存是否起效、问题出在哪,不能只看“HIT 多不多”,得把 $upstream_cache_status 稳稳记进日志,再按路径、按状态类型拆开看——六种状态(HIT/MISS/EXPIRED/BYPASS/STALE/UPDATING)各自占比,才是调优的起点。
确保缓存状态能真实写入日志
如果日志里大量出现 - 或空白,说明状态根本没采集到。检查四点:
- 对应
location块已启用proxy_cache my_cache,且my_cache在http块中通过proxy_cache_path正确定义 - 后端响应头不含
Cache-Control: no-store、Set-Cookie或Vary: *,否则 Nginx 默认跳过缓存 - 日志格式定义在
http块,且access_log指令写在该location内(作用域必须匹配) - 不把
$upstream_cache_status用在纯静态文件location中——它只对proxy_pass生效;静态资源应改用$sent_http_x_cache等自定义头
为关键路径单独切分结构化日志
别把所有流量混在同一个 access.log 里。例如分析 /api/v2/ 路径:
- 在
http块定义专用格式:log_format api_cache '$remote_addr [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $upstream_cache_status $upstream_response_time $request_time'; - 在
location /api/v2/ { ... }中启用:access_log /var/log/nginx/api_v2_cache.log api_cache; - 加调试响应头:
add_header X-Cache-Status $upstream_cache_status;,方便用curl -I快速验证单次行为
用 shell 命令快速统计状态分布
不用上 ELK 或 Prometheus,一条命令就能看出瓶颈:
- 查各状态占比:
awk '{print $12}' /var/log/nginx/api_v2_cache.log | sort | uniq -c | sort -nr - 找最常 MISS 的 URI:
grep "MISS" /var/log/nginx/api_v2_cache.log | awk '{print $7}' | sort | uniq -c | sort -nr | head -10 - 重点盯
BYPASS:说明请求被规则拦住(如带 Cookie、非 GET 方法、响应含no-cache),不是缓存没建好,而是根本没让它进缓存
命中率计算要选对分母才反映真实效率
不要用 HIT/(HIT+MISS) 这种二分算法。真实分母应是六种状态之和:
HIT / (HIT + MISS + EXPIRED + BYPASS + STALE + UPDATING)-
MISS高?检查proxy_cache_key是否含$arg_ts、$cookie_sessionid等动态变量 -
EXPIRED高?调大proxy_cache_valid或检查后端是否返回了短有效期Cache-Control -
BYPASS高?确认是否误传了认证头、或location匹配逻辑漏掉了proxy_cache指令


















