要真正用好 $upstream_cache_status 做缓存命中率监控,关键在于确保其“可采集、可区分、可计算”:需正确配置 proxy_cache、规避响应头干扰、统一日志作用域,并理解 hit/miss/expired/bypass/stale/updating 六种状态含义,分母应覆盖全部状态而非仅 hit+miss,再通过 awk 快速统计分析。

要真正用好 $upstream_cache_status 做缓存命中率监控,关键不是只加一个变量,而是让这个状态“可采集、可区分、可计算”。它本身不输出数字,但每种取值都对应一种缓存行为逻辑,日志里多出的一个词,就是优化回源效率的起点。
确保状态能真实记录到日志中
这个变量只有在启用 proxy_cache 且请求走到了带缓存配置的 location 时才有效。如果日志里始终是破折号(-)或空值,大概率是以下原因:
- 没在对应 location 中配置
proxy_cache my_cache(必须引用已定义的 cache 区) - 后端响应头含
Cache-Control: no-store或Set-Cookie,导致 Nginx 默认跳过缓存 - 用了
fastcgi_pass却误写$upstream_cache_status——此时应改用$fastcgi_cache_status - log_format 定义在 server 块内,但 access_log 写在 http 块,作用域不匹配
推荐在 http 块统一定义日志格式,并为静态资源单独切分日志文件,避免干扰主业务流:
log_format cache_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $upstream_cache_status $upstream_response_time $request_time';access_log /var/log/nginx/static_cache.log cache_log;理解六种状态背后的含义
$upstream_cache_status 不是二值开关,它的六种常见取值各自指向不同配置环节:
- HIT:缓存直接返回,理想状态
- MISS:首次请求或缓存未建立,属正常;但占比过高说明资源冷启动频繁或 key 设计不合理
-
EXPIRED:缓存过期后强制回源,通常因
proxy_cache_valid设置过短 -
BYPASS:被
proxy_cache_bypass规则触发(如用户带特定 cookie),需检查是否误配绕过条件 -
STALE:后端不可达时返回旧内容,说明
proxy_cache_use_stale生效,但后端稳定性值得排查 - UPDATING:后台正在刷新缓存,用户拿到的是旧响应,属容错设计,非错误
统计命中率时,分母应包含全部六类状态,而非仅 HIT/(HIT+MISS)。否则会高估实际缓存收益。
用简单命令实时看命中率分布
不需要上 ELK 或 Prometheus,一条 awk 就能快速摸清现状:
- 查整体 HIT 率(近一小时日志):
awk '$NF ~ /"HIT"/ {hit++} END {printf "HIT: %.2f%\n", hit/NR*100}' /var/log/nginx/static_cache.log - 统计所有状态频次:
awk '{print $NF}' /var/log/nginx/static_cache.log | sort | uniq -c | sort -nr - 对比回源耗时是否异常:
awk '$NF ~ /"MISS|EXPIRED|BYPASS/ {print $NF, $(NF-1)}' /var/log/nginx/static_cache.log | head -10(查看 MISS 时的$upstream_response_time)
注意字段位置:若日志末尾是 $upstream_cache_status,它通常是倒数第 1 或第 2 个字段,取决于 log_format 中是否加了空格或引号包裹。
命中率低时优先排查三个配置点
命中率不高,90% 以上问题出在缓存键、有效期和路径控制上:
-
缓存键太细:默认
$scheme$proxy_host$request_uri可能因 UTM 参数、随机 token 导致重复缓存。建议显式定义proxy_cache_key $host$request_uri或过滤掉无意义 query 参数 -
有效期太短:比如
proxy_cache_valid 200 302 1m会让静态资源每分钟就过期,应按资源类型分级设置(JS/CSS 可设 1h,图片设 1d) -
路径没对齐:前端请求 /api/v1/user 和 /api/v1/user/ 尾部斜杠不同,会被视为两个 key;建议用
rewrite ^(.*)/$ $1 permanent统一规范
改完配置后 reload Nginx,等几分钟再跑统计脚本,变化会立刻反映在日志分布中。











