最准方式是查看 $upstream_cache_status,但需确保启用 proxy_cache 并通过 proxy_pass 代理静态资源;若用 root/alias 则该变量无效,应改用 $sent_http_cache_control 等分析响应头。

直接看 $upstream_cache_status 是最准的方式,前提是 Nginx 正确启用了 proxy_cache 并代理了静态资源请求(比如用 proxy_pass 转发到本地文件服务或另一层后端)。如果只是用 root 或 alias 直接 serve 文件,则这个变量不生效——此时需改用 $sent_http_cache_control 和 $sent_http_expires 配合日志分析缓存头是否按预期发出。
确认缓存机制已启用且作用于静态资源
静态资源要被缓存并可监控,必须走带 proxy_cache 的路径。常见错误是:配置了 proxy_cache_path,但在 location ~* \.(js|css|png)$ 里漏写了 proxy_cache my_cache;,导致变量始终为 -。
- 确保
location块中包含proxy_pass(哪怕指向http://127.0.0.1:8080或本地 upstream),而不是仅用root - 检查后端响应是否含
Cache-Control: no-store、Set-Cookie或状态码不在proxy_cache_valid范围内,这些都会让 Nginx 跳过缓存 - 若用
fastcgi_pass(如 PHP-FPM),应改用$fastcgi_cache_status,而非$upstream_cache_status
配置专用日志格式并分离记录
避免和主业务日志混在一起,单独为静态资源 location 定义日志格式和文件:
- 在
http块中定义:log_format cache_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $upstream_cache_status $request_time'; - 在静态资源 location 中指定:
access_log /var/log/nginx/static_hit.log cache_log; - 重启 Nginx 后,访问几次静态资源,再执行
tail -n 20 /var/log/nginx/static_hit.log看是否出现HIT、MISS等值
快速统计命中率(命令行实时分析)
命中率不是只算 HIT/(HIT+MISS),而是 HIT / (HIT + MISS + EXPIRED + STALE + UPDATING + BYPASS),所有六种状态都应计入分母:
- 统计最近 1 万行中的各状态次数:
tail -n 10000 /var/log/nginx/static_hit.log | awk '{print $12}' | sort | uniq -c - 自动算出百分比(假设第 12 列是
$upstream_cache_status):awk '{a[$12]++} END {t=0; for (i in a) t+=a[i]; for (i in a) printf "%s: %.1f%%\n", i, a[i]/t*100}' /var/log/nginx/static_hit.log - 持续观察变化:
watch -n 5 'awk ...' /var/log/nginx/static_hit.log(替换上面的 awk 命令)
辅助验证:用响应头交叉确认
即使缓存未命中,只要配置了 expires 或 add_header Cache-Control,浏览器仍可能强缓存。这时日志里是 MISS,但用户实际没回源。
- 在静态资源 location 中加:
expires 1h;<br>add_header Cache-Control "public, max-age=3600";
- 用 curl 查看响应头:
curl -I https://yoursite.com/style.css→ 检查是否有Cache-Control和Expires - 配合自定义日志变量
$sent_http_cache_control记录实际发出的头,排查是否被 upstream 覆盖或遗漏











