直接用 $upstream_cache_status 统计缓存命中率需三步:一、通过日志格式与响应头双落点确保状态可采集;二、按 HIT/MISS/EXPIRED 等六类状态精准统计,公式为 HIT/(HIT+MISS+EXPIRED+STALE+UPDATING+BYPASS);三、命中率低时从缓存键、有效期、路径三维度优化。

直接用 $upstream_cache_status 统计缓存命中率,关键在日志记录、状态识别和针对性优化。它不是单纯看“HIT”多不多,而是通过状态分布反推配置是否合理、资源是否被有效复用。
一、确保状态可采集:日志与响应头双落点
只靠浏览器开发者工具看单个请求的 Nginx-Cache 响应头,无法做统计。必须把状态持久化到日志中:
- 在
http或server块中定义带缓存状态的日志格式,例如:log_format cache_log '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$upstream_cache_status"'; - 为静态资源 location 启用该日志:
access_log /var/log/nginx/static_access.log cache_log; - 同时建议添加响应头便于调试:
add_header X-Cache-Status $upstream_cache_status;
二、准确统计命中率:区分状态含义再计算
$upstream_cache_status 不只有 HIT 和 MISS,不同状态反映不同问题:
- HIT:理想状态,缓存直接返回
- MISS:首次请求或缓存未建立,正常但需关注比例
-
EXPIRED:缓存过期后回源,说明
proxy_cache_valid设置偏短 - STALE:后端不可达时返回了旧缓存,说明容错机制起作用,但后端稳定性需排查
- UPDATING:正在后台更新缓存,用户拿到的是旧内容,属正常行为
-
BYPASS:被
proxy_cache_bypass规则绕过,检查是否误配了跳过条件(如含特定 cookie)
基础命中率公式是:命中率 = HIT 数量 / (HIT + MISS + EXPIRED + STALE + UPDATING + BYPASS)
推荐用 awk 统计(注意引号转义):awk '$NF ~ /"HIT"/ {hit++} END {printf "%.2f%\n", hit/NR*100}' /var/log/nginx/static_access.log
三、命中率低?从三个维度定位原因
命中率低于 70% 时,优先检查以下配置项:
-
缓存键(proxy_cache_key)是否太细粒度:比如包含
$cookie_sessionid或$arg_ts(时间戳参数),会导致同一资源生成多个缓存副本。应精简为$host$request_uri,必要时用map过滤无关参数 -
缓存有效期(proxy_cache_valid)是否过短:静态资源如 JS/CSS/图片通常设为
200 304 7d;若大量出现 EXPIRED,说明设置小于实际更新周期 -
缓存路径(proxy_cache_path)空间或淘汰策略是否不合理:
inactive=60m表示 60 分钟未访问即清理,对低频但需长期保留的资源不友好;max_size过小会频繁触发 LRU 清理,导致热数据被挤出
四、进阶优化:结合延迟与状态联动分析
光看命中率不够,要结合响应耗时判断缓存质量:
- 扩展日志格式,加入
$upstream_cache_time:log_format cache_perf '$upstream_cache_status $upstream_cache_time $upstream_response_time $request_time'; - 若 HIT 请求的
$upstream_cache_time普遍 >50ms,说明磁盘缓存慢(如用 HDD),应启用use_temp_path=off减少写临时文件,并考虑迁移到 SSD 或增大内存缓存区(keys_zone) - 若 MISS 请求的
$upstream_response_time显著高于 HIT 的$request_time,说明后端压力大,缓存确实起到了卸载作用——此时提升命中率比调优单次响应更重要


















