要在 nginx 访问日志中准确统计 hit 与 miss,需配置含 $upstream_cache_status 的日志格式、明确各状态含义(如 expired/bypass 实际回源)、用 awk 精确统计并排除干扰项,再结合响应头 x-cache-status 实时验证。

要在 Nginx 访问日志中准确分类统计 HIT 与 MISS,关键不是简单数“HIT”出现几次,而是让日志真实、结构化地记录缓存行为,并排除干扰项。直接 grep 或粗略计数容易失真,必须从日志配置、状态含义、统计口径三方面入手。
确保日志里真有缓存状态字段
默认 access_log 不含缓存信息,需显式启用:
在 http 或 server 块中定义带 $upstream_cache_status 的日志格式:
log_format cache_log '$remote_addr [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $upstream_cache_status $upstream_response_time';- 在对应 location(尤其是 proxy_pass 的位置)启用该格式:
access_log /var/log/nginx/static.log cache_log; - 重启 Nginx 后,用
tail -1 /var/log/nginx/static.log确认末尾字段是否为 HIT/MISS/EXPIRED 等——若大量是-,说明变量未生效,需检查 proxy_cache 是否启用、location 是否匹配。
区分 HIT 和 MISS 的实际含义
不能把所有 HIT 都当成“有效节省”,也不能把所有 MISS 都归为“配置失败”:
- HIT:缓存新鲜且直接返回,真正降低后端压力和延迟
-
MISS:首次访问或 key 不一致(如 URL 带 utm 参数但没从
proxy_cache_key中剔除),属正常冷启动;但如果占比持续超 30%,需查 key 设计或缓存有效期 - 注意排除干扰状态:EXPIRED、BYPASS、STALE 虽非 MISS,但实际都触发了回源,不应计入“理想命中”;统计时建议单独列示,而非混进 HIT 或 MISS
用 awk 精确统计 HIT 与 MISS 比例
假设 $upstream_cache_status 是日志第 10 字段(按空格分割),可用以下命令:
- 分别统计数量:
awk '{print $10}' /var/log/nginx/static.log | sort | uniq -c - 计算 HIT 占比(分母为所有含状态的请求):
awk '$10=="HIT"{h++} $10~/^(HIT|MISS|EXPIRED|BYPASS|STALE|UPDATING)$/{t++} END{printf "%.1f%\n", h/t*100}' /var/log/nginx/static.log - 若想看 MISS 主要来自哪些路径,加过滤:
awk '$10=="MISS"{print $3}' /var/log/nginx/static.log | sort | uniq -c | sort -nr | head -5
配合响应头快速验证单次行为
光看日志滞后,调试时建议同步输出响应头:
- 在 location 中加:
add_header X-Cache-Status $upstream_cache_status always; - 用
curl -I https://example.com/js/app.js直接查看头信息,确认是 HIT 还是 MISS - 连续刷新观察变化:首次 MISS → 二次 HIT,说明缓存写入成功;若始终 MISS,重点检查后端是否返回
Cache-Control: no-store或请求头是否含Cookie触发了proxy_cache_bypass











