核心是让每个Range请求走缓存而非回源,需显式将$http_range加入proxy_cache_key、配置proxy_cache_valid支持206响应、用proxy_cache_bypass和proxy_no_cache避免干扰,并添加Vary: Range等头确保协同。

核心不是压低 Range 请求量,而是让每个 Range 请求都走缓存、不打后端——前提是缓存能正确识别并区分不同字节范围,且不因配置冲突导致穿透或降级。
确保缓存键真实携带 Range 信息
默认缓存 key(如 $uri $args)完全忽略 Range 头,所有分片请求都命中同一个缓存条目,结果要么返回错误字节段,要么被 Nginx 降级为全量 200 响应,反复回源。必须显式把 Range 加入 key:
- 推荐写法:proxy_cache_key "$uri|$http_range";——简洁、兼容空值(全量请求时 $http_range 为空,key 自动变为 /file.zip|,与 /file.zip|bytes=0-1023 不冲突)
- 避免用 $slice_range(需启用 slice 模块),除非你已统一用 slice 切分并控制分片逻辑
- 若 URL 含随机参数(如 ?t=1716825783),先用 map 提取纯净路径再拼接,防止缓存碎片化
明确允许缓存 206 响应并设合理有效期
Nginx 默认不缓存 206 响应,即使 key 正确也每次穿透。必须主动声明:
- proxy_cache_valid 200 206 1h;——同时覆盖完整响应和分片响应,1 小时是较稳妥起点,可按文件更新频率上调
- 不要依赖 proxy_cache_valid 的默认行为,也不要用 206 0s 这类无效写法
- 对长期不变的大文件(如安装包、课程视频),可设为 24h 或更长;对频繁更新的资源,缩短至 10–30 分钟
绕过缓存干扰,防止 Range 请求被“误伤”
某些缓存策略会强行将 Range 请求导向回源,比如 Cache-Control: no-cache 或 CDN 的“强制校验”开关。Nginx 层需主动拦截:
- proxy_cache_bypass $http_range;——有 Range 头就跳过缓存查找,直接进入代理流程(配合上面的 cache_key 才有意义)
- proxy_no_cache $http_range;——有 Range 头就不存响应到缓存(仅适用于你希望只读缓存、不写缓存的场景)
- 更常用组合是:proxy_cache_bypass $http_range; proxy_no_cache $http_range;,即:有 Range 就不查也不存,靠 cache_key + cache_valid 实现精准缓存复用
补充关键头信息,协助客户端与中间层协同
光服务端缓存到位还不够,客户端和 CDN 需知道这个资源支持分片、且不同 Range 应视为不同实体:
- add_header Vary "Origin, Range";——告诉缓存系统:响应内容随 Origin 和 Range 变化,不可混用
- 确认后端返回 Accept-Ranges: bytes,且未被 Nginx 或 WAF 覆盖或删除
- 禁用对 Range 请求的 gzip:gzip_disable "Range";,避免压缩干扰 206 响应结构


















