nginx 默认不缓存重定向响应(如301/302),因其由nginx自身生成、绕过proxy_cache流程,且客户端已自行缓存;真正有效的是缓存重定向目标内容,并通过map+return实现零开销跳转决策、try_files+命名location或proxy_pass后端接口返回可缓存的301响应。

直接说结论:Nginx 本身不缓存重定向响应(如 301/302),但可以通过组合策略实现“重定向逻辑的高效执行”和“重定向目标内容的缓存”,从而间接提升重定向链路的整体性能。关键在于区分清楚——缓存的是重定向动作本身,还是重定向后最终返回的内容。
为什么不能直接缓存重定向响应?
Nginx 的内置缓存模块(proxy_cache、fastcgi_cache)默认只缓存 200、301、302、304 等状态码的响应体,但有一个重要限制:301/302 响应本身体积极小(仅含 Location 头),且多数客户端会自行缓存该跳转(尤其 301),服务端再缓存意义不大。更重要的是:
- Nginx 不会对
return 301 ...或rewrite ... permanent这类纯控制流指令生成的响应做缓存(它们发生在请求处理早期,绕过缓存阶段); -
proxy_cache只作用于proxy_pass后端响应,而重定向通常由 Nginx 自身生成,不经过 proxy 流程; - 若强行用
proxy_cache_valid 301 1h;,需配合proxy_pass回环或上游服务返回 301,实际中极少这样设计。
真正有效的“重定向+缓存”协同方案
核心思路:把“是否需要重定向”的判断逻辑前置并固化,让高频请求快速命中缓存结果,避免重复计算;同时确保重定向后的目标资源(新 URL 内容)被充分缓存。
-
用 map + return 实现零开销跳转:对大量固定路径映射(如旧文章 ID → 新路径),用
map预编译为变量,配合return 301 $new_uri;。整个过程无正则匹配、无 location 查找,CPU 开销趋近于零,等效于“缓存了跳转决策”; -
对重定向目标页面启用强缓存:例如 /new-page 被大量访问,就在其 location 中配置:
location /new-page {<br> proxy_cache my_cache;<br> proxy_cache_valid 200 302 10m;<br> proxy_pass http://backend;<br>}—— 这样用户首次跳转后,后续访问新地址直接走缓存; -
用 try_files 实现内部重写+缓存融合:适用于 SPA 或静态迁移场景。例如:
location / {<br> try_files $uri @redirect_fallback;<br>}<br>location @redirect_fallback {<br> # 查表或调用后端判断是否需跳转<br> proxy_pass http://redirect-service;<br> proxy_cache redirect_cache;<br>}—— 把跳转决策交给可缓存的后端接口,Nginx 缓存该接口返回的 301 响应(需后端明确设置 Cache-Control)。
避坑提醒:哪些操作会破坏缓存效果
以下配置看似合理,实则让缓存失效或引发问题:
- 在
rewrite指令中使用last或break后又依赖proxy_cache:rewrite 是内部 URI 修改,不触发新响应缓存; - 重定向目标 URL 包含动态参数(如
/new-page?id=123)却未在proxy_cache_key中包含$args:不同参数会被当作同一缓存键,导致内容错乱; - 后端返回 301 时带
Cache-Control: no-store或Set-Cookie:Nginx 默认不缓存含 Set-Cookie 的响应,需显式配置proxy_ignore_headers Set-Cookie;并谨慎评估风险。
简单验证是否生效
加一条日志格式,观察缓存命中情况:log_format cache '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$upstream_cache_status"';
其中 $upstream_cache_status 会显示 HIT、MISS、BYPASS 等值。重点确认重定向目标资源(而非跳转本身)是否稳定命中 HIT。











