核心思路是让nginx透传range请求给后端,禁用其自主处理:设proxy_force_ranges off、透传range/if-range头、关闭缓冲与缓存干扰,并配合后端正确支持range及限流。

核心思路不是“限制 Range 请求”,而是让 Nginx 不插手 Range 处理,交由后端源站自主响应,同时避免代理层引发的重复请求、缓存干扰或头信息丢失。
禁用 Nginx 对 Range 请求的代理干预
Nginx 默认会尝试接管并重写 Range 请求:它向后端拉取完整资源,再自行截取字节范围返回。这在音视频分片场景下极易造成后端反复传输大文件,引发带宽和 CPU 过载。
- 添加 proxy_force_ranges off; —— 关闭 Nginx 自行处理 206 响应的能力
- 确保 Range 和 If-Range 请求头透传:
proxy_set_header Range $http_range;
proxy_set_header If-Range $http_if_range; - 关闭缓冲以防止 Nginx 缓存或拼接不完整响应:
proxy_buffering off;
阻止缓存干扰 Range 行为
若启用了 proxy_cache,Nginx 可能对相同 URL 的不同 Range 请求复用缓存(尤其是未带 Vary: Range 的情况),导致返回错误字节段,迫使客户端重试,进一步加重后端压力。
- 绕过缓存所有含 Range 头的请求:
proxy_cache_bypass $http_range;
proxy_no_cache $http_range; - 显式禁止对 206 响应进行缓存:
proxy_cache_valid 206 1m;(设极短时间,或直接不配 206) - 建议在响应头中加入:
add_header Vary "Origin, Range";(兼顾跨域与分片缓存隔离)
配合后端做好 Range 支持与限流
仅靠 Nginx 透传不够,源站必须正确支持 Range,并具备基础防护能力:
- 确认后端返回 Accept-Ranges: bytes,且不被 Nginx 或中间层覆盖/删除
- 后端应校验 Range 值合法性(如避免超大 offset、负数、格式错误),拒绝非法请求而非返回 200+全量内容
- 对高频 Range 请求(如单个 IP 短时间内大量小范围请求)可在后端或 Nginx 层叠加限流:
使用 limit_req 按 IP 限制 /video/.*\.mp4 路径的请求速率,例如:
limit_req_zone $binary_remote_addr$uri zone=range_limit:10m rate=5r/s;
location ~ \.mp4$ { limit_req zone=range_limit burst=10; ... }
验证是否生效
不要只看响应状态码,重点检查实际链路行为:
- 用 curl 发起带 Range 的请求:
curl -I -H "Range: bytes=0-1023" https://your.domain/video.mp4
应看到 HTTP/2 206、Content-Range、Accept-Ranges: bytes,且 Server 头显示后端服务名(非 nginx) - 检查 Nginx access log,确认该请求未触发多次 upstream 请求(即无重复 upstream_addr 记录)
- 抓包或查看后端日志,确认后端收到 Range 头并直接生成 206,而非返回 200 全量响应











