Nginx 无法用原生 expires 指令为不同 HTTP 状态码设置差异化缓存头,因其仅对 2xx/3xx 响应生效;需改用 map + add_header ... always 实现:在 http 块定义 $status 到 Cache-Control 策略的映射,再于 location 中统一注入,如 404 缓存 1 小时防探测、500 缓存 60 秒防雪崩,并确保 always 参数覆盖所有状态码。

直接对不同 HTTP 状态码设置差异化 expires 头部,在 Nginx 中无法通过原生 expires 指令实现——因为该指令只作用于响应体存在且状态码为 2xx/3xx 的成功响应,对 4xx/5xx 错误响应默认不生效,也无法按状态码条件分支配置。
核心原则:用 add_header + always + 条件判断替代 expires
要让 404、500、304 等状态码也携带定制化的缓存控制头,必须放弃 expires,改用 add_header ... always 配合 if 或 map 判断响应状态:
-
add_header默认只对 200/301/302 等标准成功响应生效;加always参数后,才能覆盖 304、404、500 等所有状态码 - 不能在
if ($status = 404) { ... }中直接写add_header(Nginx 语法禁止),必须先用map将状态码映射为变量,再基于该变量输出头 - CDN 边缘节点是否尊重 4xx/5xx 的缓存头,取决于其策略(如 Cloudflare 默认不缓存 404,但可开启「Cache Everything」并配合 Page Rule);因此需确认 CDN 支持且已启用对应能力
推荐配置:用 map 构建 status_cache_control 变量
在 http 块顶层定义状态码到缓存策略的映射:
map $status $status_cache_control {
default "no-store";
200 "public, max-age=31536000, immutable";
301 "public, max-age=31536000";
302 "private, max-age=600";
304 "public, max-age=31536000";
404 "public, max-age=3600"; # 404 缓存 1 小时,减少反复探测
410 "public, max-age=86400"; # Gone 资源长期失效,缓存 1 天
500 "private, max-age=60"; # 后端错误临时缓存 1 分钟,防雪崩
502 "private, max-age=30";
503 "private, max-age=10";
}然后在 server 或 location 块中统一注入:
add_header Cache-Control $status_cache_control always;
注意:always 是关键,否则 404/500 响应不会带这个头;$status_cache_control 值必须是合法字符串(不含空格或特殊字符),否则可能被 CDN 截断或忽略。
为什么需要差异化设置 4xx/5xx 的缓存头
边缘 CDN 二次检索率高,往往不是因为 200 响应没缓存好,而是大量重复的 404 请求打到源站——比如旧链接未清理、爬虫扫废弃路径、前端路由 fallback 错误等。给 404 设置 max-age=3600 后:
- CDN 会缓存该 404 响应 1 小时,后续相同请求直接返回,不回源
- 避免源站被无效请求压垮,尤其对静态资源服务器(如纯 Nginx 托管)效果明显
- 5xx 类错误缓存极短时间(如 30–60 秒),既缓解瞬时故障冲击,又不掩盖真实问题
配套建议:限制作用范围,避免污染健康响应
不要全局启用,应在明确的静态资源 location 中使用:
location ~* \.(js|css|png|jpg|gif|ico|svg|woff2|eot|ttf)$ {
add_header Cache-Control $status_cache_control always;
# 其他静态优化:sendfile, open_file_cache 等
}对于 HTML 或 API 接口,通常不应缓存错误响应(尤其是 5xx),可单独设为空或禁用:
location ~* \.html$ {
add_header Cache-Control "no-cache, no-store" always;
}若业务允许,还可对特定路径(如 /assets/)启用更激进的 404 缓存,而对 /api/ 保持 404 不缓存。


















