应使用 $upstream_cache_status 配合 add_header 设置 X-Cache 响应头,而非尝试赋值只读的 $sent_http_x_cache;该变量自动反映缓存状态(HIT/MISS/EXPIRED/BYPASS),可结合 map 实现语义化描述。

可以通过在 Nginx 配置中主动设置 $sent_http_x_cache 响应头,来向客户端暴露缓存命中状态(如 HIT / MISS / EXPIRED / BYPASS),但需注意:该变量本身是只读的“输出响应头变量”,不能直接赋值;真正可行的方式是使用 add_header 结合 Nginx 内置变量或自定义 map 映射,动态注入缓存行为标识。
理解 $sent_http_x_cache 的本质
$sent_http_x_cache 并非可写变量,而是 Nginx 在响应发送后自动记录的“已发出的 X-Cache 头原始值”——它本身不生成缓存状态,只是反射你通过 add_header X-Cache ... 设置的内容。所以实际操作中,你需要自己构造这个头,而不是“修改”它。
常见做法是配合 proxy_cache_status 变量(由 proxy_cache 模块提供)来判断本次请求是否命中边缘缓存:
-
HIT:缓存有效且直接返回 -
MISS:未命中,回源拉取并可能缓存 -
EXPIRED:缓存过期,回源验证后返回(若启用 stale) -
BYPASS:因配置绕过缓存(如带特定 Cookie 或请求头) -
REVALIDATED:使用 If-Modified-Since/ETag 验证后确认未变
在 Nginx 中添加 X-Cache 响应头
确保已启用 proxy_cache,并在 location 块中加入:
location / {
proxy_pass http://origin;
proxy_cache my_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
<pre class="brush:php;toolbar:false;"># 关键:将 proxy_cache_status 映射为人类可读状态
add_header X-Cache $upstream_cache_status;
}
其中 $upstream_cache_status 是 Nginx 官方提供的标准变量(注意不是 $sent_http_x_cache),会自动携带上述 HIT/MISS 等值。浏览器或调试工具即可通过响应头看到边缘节点的缓存决策结果。
进阶:按业务逻辑定制 X-Cache 描述
若需更语义化的提示(例如区分 CDN 缓存 vs 自建反向代理缓存),可用 map 构建多级标识:
map $upstream_cache_status $cache_desc {
default "MISS";
HIT "HIT from edge";
EXPIRED "STALE served, revalidating";
BYPASS "BYPASS: user-specific request";
}
<p>server {
...
location / {
...
add_header X-Cache "$cache_desc ($upstream_cache_status)";
}
}</p>
这样响应头类似:X-Cache: HIT from edge (HIT),既保留机器可解析字段,又增强运维可读性。
注意事项与常见问题
启用该头不会影响缓存行为本身,但要注意以下几点:
- 确保
underscores_in_headers on;已开启(如果使用下划线命名的自定义头) -
add_header在子请求(subrequest)中不生效,仅对主响应有效 - 若使用了多个 cache zone 或分层缓存(如 ESA + Nginx),
$upstream_cache_status仅反映最靠近 upstream 的那层缓存状态 - 部分 CDN(如阿里云 ESA)会默认透传或覆盖
X-Cache,此时应优先以厂商控制台的缓存日志为准
不复杂但容易忽略的是:这个头只对开启 proxy_cache 的 location 生效;静态文件直出(如 root + try_files)场景需改用 expires 和 add_header 组合模拟逻辑,无法获取真实缓存状态。










