Nginx可通过map指令识别Range请求并结合limit_conn实现精准并发限制:利用$http_range变量映射出仅含IP的$range_key,定义专用限流区zone=range_perip,在location中对静态文件路径启用limit_conn range_perip N,使同一IP最多N个Range并发连接,超限返回503。

直接限制 Range 请求的并发数,Nginx 本身不提供“仅针对 Range 请求”的专用指令,但可以通过组合 limit_conn + 请求特征识别 + 合理作用域来精准防控——核心思路是:**把 Range 请求单独标记出来,再对其施加连接级限流**。
识别并标记 Range 请求
Range 请求的典型特征是请求头中包含 Range 字段(如 Range: bytes=0-1023)。Nginx 可用内置变量 $http_range 捕获该值。若该变量非空,说明是分块下载请求。
-
$http_range有值时为字符串(如bytes=0-1023),为空时为空字符串 - 不能直接用
$http_range做limit_conn_zone的 key(因内容不固定、无法聚合),但可结合 IP 构造复合键
构造专用限流区域(按 IP + Range 行为)
在 http 块中定义一个仅对 Range 请求生效的连接计数区:
http {
# 仅当存在 Range 头时,才使用该 key;否则设为空字符串(不计入计数)
map $http_range $range_key {
"" ""; # 无 Range,key 为空 → 不触发限流
default $binary_remote_addr; # 有 Range,以二进制 IP 为 key
}
<pre class="brush:php;toolbar:false;">limit_conn_zone $range_key zone=range_perip:10m;}
-
map指令将$http_range映射为$range_key:只有带 Range 的请求才生成有效 key(即客户端 IP) - 未带 Range 的请求(普通 HTML、API 等)
$range_key为空,limit_conn对其完全不计数,不影响正常流量 -
zone=range_perip:10m提供足够空间存储数十万 IP 的连接状态
在 location 中启用并发限制
针对静态文件路径(如 /download/、/files/)应用限流,避免影响动态接口:
location ^~ /download/ {
# 只对 Range 请求限并发,例如每个 IP 最多 3 个 Range 连接
limit_conn range_perip 3;
<pre class="brush:php;toolbar:false;"># 可选:同时限制单连接带宽,防大块连续读压垮磁盘 I/O
limit_rate 2m;
# 静态文件服务
alias /data/files/;
expires 7d;}
-
limit_conn range_perip 3表示:同一 IP 发起的 Range 请求,最多维持 3 个并发 TCP 连接 - 若第 4 个 Range 请求抵达,Nginx 直接拒绝(返回 503),不建立连接、不读磁盘、不触发 sendfile
-
limit_rate 2m(即 2MB/s)进一步约束单连接吞吐,避免单个 Range 连接持续占满磁盘带宽
增强防护:区分可信用户与匿名下载
若系统支持登录态(如通过 cookie 或 token),可进一步放宽内部用户限制:
map $cookie_user_id $range_limit {
"" 1; # 匿名用户:仅允许 1 个 Range 并发
default 5; # 登录用户:允许 5 个
}
<p>limit_conn_zone $binary_remote_addr zone=range_trusted:10m;</p><p>location ^~ /download/ {
limit_conn range_trusted $range_limit;
limit_rate 3m;
}- 利用
map动态设置limit_conn的数值参数,实现差异化策略 - 无需修改后端逻辑,纯 Nginx 层即可完成权限感知限流
这套配置不依赖外部模块,全部基于 Nginx 内置功能,生效快、开销低、可精确控制磁盘 I/O 压力源头。关键点在于用 map 实现请求类型路由,让限流只落在真正危险的 Range 流量上。


















