需在nginx中通过log_format捕获$sent_http_cache_control监控强缓存准确率:确保上游设置cache-control、避免add_header干扰、用专用log_format按路径记录、再用awk统计含max-age=31536000的响应占比。

要通过 log_format 捕获 $sent_http_cache_control 并监控特定路径下资产强缓存响应头的下发准确率,核心在于:正确声明日志格式、精准匹配目标路径、确保 Nginx 在响应阶段已生成该变量、并结合日志分析工具做统计校验。
确认 $sent_http_cache_control 可用且非空
$sent_http_cache_control 是 Nginx 内置变量,仅在响应头已写入(即 header_filter 阶段之后)才可读取。它不会回溯未设置的响应头——若后端未返回 Cache-Control,该变量为空字符串(不是 - 或 NULL)。因此:
- 确保上游服务(如 Node.js、Python 应用或静态文件服务)对目标路径明确设置了
Cache-Control: public, max-age=31536000等强缓存策略 - 避免在 Nginx 中用
add_header Cache-Control ...覆盖或干扰——该指令发生在add_header阶段,晚于$sent_http_cache_control的捕获时机,无法影响该变量值 - 可通过调试日志验证:
error_log /var/log/nginx/debug.log debug;+log_format debug '$sent_http_cache_control $request_uri';,观察真实输出
定义带路径过滤与缓存头记录的日志格式
在 http 块中定义专用日志格式,同时包含路径匹配标识和缓存头内容:
log_format cache_check '$time_iso8601|$request_uri|$status|$sent_http_cache_control|$upstream_http_cache_control';
其中:
- $request_uri 用于后续按路径筛选(如 /static/js/app.min.js)
- $sent_http_cache_control 记录实际下发的值(如 public, max-age=31536000)
- $upstream_http_cache_control 可选,用于比对上游原始响应头,排查是否被 Nginx 中间层修改
注意:该格式需配合 access_log 使用,且建议仅对目标 location 启用,减少日志冗余:
location ~ ^/static/(js|css|img)/ {
access_log /var/log/nginx/cache_check.log cache_check;
# 其他配置...
}
统计“强缓存下发准确率”的关键逻辑
准确率 = (符合预期强缓存策略的响应数) ÷ (该路径总响应数) × 100%。需明确定义“符合预期”:
- 预期值示例:
public, max-age=31536000、immutable, max-age=31536000,或至少含max-age=且数值 ≥ 31536000 - 排除项:
no-cache、no-store、max-age=0、空值、仅must-revalidate等弱缓存或禁用缓存的情况 - 推荐用 awk 或 logstash 提取统计:
awk -F'|' '$2 ~ /^\/static\/js\// && $4 ~ /max-age=31536000/ {hit++} $2 ~ /^\/static\/js\// {total++} END {print "Accuracy: " (total>0 ? int(hit/total*100) : 0) "%"}' /var/log/nginx/cache_check.log
规避常见陷阱
以下情况会导致 $sent_http_cache_control 不可用或失真:
-
gzip/vary 干扰:若启用了
gzip on且响应含Vary: Accept-Encoding,Nginx 可能重写Cache-Control(如添加no-transform),需检查实际响应头是否与日志一致 -
条件缓存逻辑覆盖:如使用
expires指令,它会自动设置Cache-Control和Expires,此时$sent_http_cache_control反映的是 Nginx 生成的值,而非上游原始值 -
HTTP/2 推送资源不触发 access_log:被
http2_push推送的资源不会经过常规请求生命周期,其响应头不会记入 access_log,无法被此方案捕获











