关键在于精准区分缓存粒度,fastcgi_cache_key需包含$scheme$request_method$host$request_uri及必要$args,剔除utm_source等干扰参数,避免缓存混乱或击穿。

关键不在“写全”,而在“精准区分缓存粒度”。fastcgi_cache_key 决定请求是否命中已有缓存,配错会导致缓存混乱、内容错乱或大量击穿。
必须包含的核心变量
基础组合 $scheme$request_method$host$request_uri 是起点,但仅靠它远远不够:
-
$request_uri 包含路径和原始 query 字符串(如
/search.php?s=nginx),但默认不区分参数顺序或多余空格,实际中易出错 -
$args 应显式加入——尤其对 WordPress、Typecho 等依赖 GET 参数的系统。否则所有带
?s=xxx的搜索页会被当成同一个 URI,全部共用一份缓存 - 不要加 $cookie_* 或 $http_user_agent:除非你明确要做登录态/设备级差异化缓存(如会员专属页),否则它们会让缓存碎片化,严重降低命中率
需要过滤的干扰参数
广告跟踪、A/B 测试、埋点类参数(如 utm_source、ref=abc、v=1.2.3)不应影响缓存逻辑:
- 不能靠
fastcgi_ignore_headers处理——它只管响应头,不管请求键生成 - 正确做法是用
map预处理$args,例如:
default "";
"~^(.*&)?(utm_[^&]+)(?:&.*)?$" "$1";
"~^(.*&)?(ref|v)=[^&]+(?:&.*)?$" "$1";
"^$" "";
}
再把 fastcgi_cache_key 改为 "$scheme$request_method$host$request_uri?$cache_args",就能干净剔除干扰项。
容易被忽略的协议与请求方法细节
HTTP/2 升级、HTTPS 重定向、AJAX POST 请求都可能让缓存失效或误命:
- 若站点同时支持 HTTP 和 HTTPS,
$scheme能自然隔离;但若反向代理层做了协议转换(如前端 HTTPS → 后端 HTTP),需确认$scheme是否被真实传递 -
$request_method对缓存很关键:GET 和 HEAD 可缓存,POST/PUT/DELETE 默认不缓存(Nginx 不会自动缓存非幂等方法的响应) - 某些 AJAX 接口用 POST 提交查询参数,此时需配合
fastcgi_cache_methods POST;显式开启,并确保后端响应头允许缓存(如Cache-Control: public, max-age=300)
验证与调试建议
上线前务必检查缓存行为是否符合预期:
- 在
log_format中加入$upstream_cache_status,观察日志里是HIT、MISSED还是BYPASS - 用
curl -I查看响应头,确认X-Cache或自定义头是否反映真实缓存状态 - 对同一 URL 带不同参数反复请求,用
find /var/cache/nginx/fastcgi -name "*your-key-hash*"检查磁盘上是否生成了多个缓存文件——如果数量异常多,大概率是cache_key过细











