nginx无法原生按响应体大小动态拒绝缓存,但可通过map匹配$sent_http_content_length与proxy_cache_bypass组合实现:当content-length≥10mb时跳过缓存,辅以路径正则兜底和缓冲区调优确保安全。

Nginx 代理缓存本身不提供“按响应体大小动态拒绝缓存”的原生指令,但可通过组合配置实现自动识别 + 条件跳过缓存 + 安全兜底的效果。关键不是让缓存系统“拦截”大响应,而是让 Nginx 在缓存决策阶段就排除它们——既避免缓存污染,又防止磁盘撑爆或响应截断。
核心思路:用 proxy_cache_bypass + map 提前判断响应大小,配合 proxy_cache_valid 的精准控制
明确缓存拒绝的触发条件
Nginx 只能在收到响应头后、响应体传输前得知 Content-Length(若后端正确返回),因此判断依据只能是:
- 响应头中的
Content-Length字段(最可靠) - 或响应状态码 + URL 路径特征(辅助兜底,如
/export/,/download/)
⚠️ 注意:Content-Length 缺失时(如流式响应、chunked transfer),Nginx 无法预判体积,此时应默认不缓存(靠 proxy_buffering off 或 proxy_cache_bypass 强制绕过)。
配置步骤:分级过滤超大响应
1. 定义体积阈值映射(推荐 10MB 为界)
在 http 块中添加:
map $sent_http_content_length $skip_cache_by_size {
~^[0-9]{8,}$ "1"; # Content-Length ≥ 10MB(即 ≥10,000,000 字节 → 8位及以上数字)
default "";
}
说明:正则 ^[0-9]{8,}$ 匹配至少 8 位数字(最小值为 10,000,000),覆盖 10MB–99MB;若需支持 100MB+,可改用 ^[1-9][0-9]{7,}$ 更严谨。
2. 在 location 中启用条件缓存跳过
location /api/ {
proxy_pass http://backend;
# 关键:满足任一条件即跳过缓存
proxy_cache_bypass $skip_cache_by_size $arg_nocache;
# 仅缓存小响应(200/201)且明确有 Content-Length 的
proxy_cache_valid 200 201 1h;
proxy_cache_valid 404 1m;
# 禁止缓存无长度或流式响应
proxy_cache_valid 200 201 1h;
proxy_ignore_headers Cache-Control Expires Set-Cookie;
add_header X-Cache-Status $upstream_cache_status;
}
✅ 效果:当 Content-Length ≥ 10MB,$skip_cache_by_size 为 "1" → proxy_cache_bypass 生效 → 不写入缓存,直接透传。
3. 补充安全兜底:对已知大响应路径强制禁用缓存
针对固定出口(如报表导出、文件下载),直接关闭缓存更稳妥:
location ~ ^/(export|download|stream)/ {
proxy_pass http://backend;
proxy_cache off; # 彻底禁用,不走任何缓存逻辑
proxy_buffering off; # 边收边发,防内存堆积
proxy_read_timeout 600;
}
必须同步调整的关联项
确保后端返回
Content-Length
Spring Boot 加server.tomcat.max-http-header-size=65536;Node.js Express 用res.setHeader('Content-Length', size);避免 chunked。-
限制缓存区不被大响应挤占
proxy_buffer_size 128k; proxy_buffers 8 256k; # 总缓冲 ≤ 2MB,防大响应填满 proxy_busy_buffers_size 512k;
-
监控是否生效
查看日志中X-Cache-Status头:-
MISS:未命中(正常) -
BYPASS:被proxy_cache_bypass绕过(预期中的大响应) -
EXPIRED/STALE:缓存生效
同时检查 error log 是否出现upstream sent too big header—— 若有,说明缓冲区仍不足,需调大proxy_buffer_size。
-
不推荐的做法
❌ 试图用 if 指令判断 $sent_http_content_length:Nginx 不允许在 if 中使用 sent_http_* 变量,会报错或失效。
❌ 单独依赖 proxy_max_temp_file_size 控制响应缓存:该参数只影响临时文件写入行为,不参与缓存决策逻辑。
❌ 把 proxy_cache_valid 设成 200 0s:这会导致所有 200 响应都不缓存,失去选择性。
不复杂但容易忽略。











