关键在于精准构造缓存键(key),使相同语义请求生成同一key、不同语义生成不同key;nginx仅按proxy_cache_key哈希存储,命中率取决于其合理性,需剔除无关参数、预处理动态值、谨慎选取header/cookie字段,并通过响应头和日志验证效果。

关键不是“定义结构”,而是精准构造缓存键(key),让相同语义的请求生成同一个 key,不同语义的请求生成不同 key。Nginx 本身不管理“缓存结构”,它只按你给的 proxy_cache_key 字符串做哈希存储,真正决定命中率的是这个字符串是否合理。
只保留影响响应结果的变量
默认 $scheme$proxy_host$request_uri 包含全部 query 参数,但很多参数(如 utm_source、_ga、t=时间戳)纯属前端埋点或防缓存用,后端根本不读取——它们只会把本该复用的缓存拆成无数个碎片。
- 静态资源建议用:
proxy_cache_key "$scheme$host$uri";(去掉所有 args) - API 接口需保留业务相关参数:如
$arg_lang、$arg_region、$arg_v(版本号),剔除utm_*、ref=*、t=*等 - 避免直接拼
$args,它不稳定且易带干扰项
用 map 预处理动态值,保持 key 干净
直接在 proxy_cache_key 里写复杂逻辑不可读也不可控。推荐用 map 提前提取/标准化关键字段:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
- 例如区分中英文:
map $http_accept_language $lang { ~zh en; default en; },然后 key 中用$lang - 识别移动端:
map $http_user_agent $mobile_flag { ~*android|ios "mobile"; default "desktop"; },再加入 key - 清理 utm 参数:
map $args $clean_args { ~^(.*&)?(utm_[^&]+&?)+(.*)?$ "$1$3"; default $args; }(需配合正则谨慎使用)
注意 Cookie 和 Header 的取舍
除非接口真依赖 Cookie(如登录态、灰度标识),否则一律不进 key。常见误区是把 $cookie_session 或 $http_cookie 直接塞进去,结果每个用户都缓一份,完全失去共享意义。
- 需要区分用户级缓存时,只取特定字段,比如
$cookie_user_role或$http_x_gray_version - 语言/地区类 Header 可保留:
$http_accept_language、$http_x_region - 绝对避免
$cookie、$http_referer、$http_x_forwarded_for这类高变字段
验证与调试不能跳过
改完 key 后必须确认效果,否则只是纸上谈兵:
- 加响应头:
add_header X-Cache-Status $upstream_cache_status;,看是HIT还是MISSED - 开 cache log:
log_format cache '$remote_addr - $upstream_cache_status $request';,观察实际生成的 key 是否符合预期 - 用
curl -I多次请求带/不带 utm 的同一 URL,对比X-Cache-Status和Age头










