可通过geo指令按IP划分用户组并结合map映射为限速值,再在location中用limit_rate引用变量实现差异化带宽控制,支持limit_rate_after“先快后慢”策略。

可以通过 geo 指令划分用户来源(如国家、IP段、运营商),再结合 limit_rate 或更灵活的 limit_rate_after 实现差异化带宽控制。核心在于用 geo 生成变量,再在 location 或 server 块中引用该变量动态设置限速值。
用 geo 定义用户分组变量
geo 指令必须放在 http 块中,用于根据客户端 IP 匹配规则并赋值给自定义变量。它不支持正则,但支持 CIDR、范围和默认值:
http {
# 定义 $user_group 变量:中国用户限速 1m,海外用户限速 512k,其他为 256k
geo $user_group {
default "overseas"; # 默认值(未匹配时)
114.114.114.0/24 "cn"; # 举例:某国内 DNS 段
202.96.0.0/16 "cn";
1.2.3.0/24 "isp_a"; # 某运营商
2001:da8::/32 "cn"; # 支持 IPv6
}
}注意:geo 不支持 Host 或 UA 判断;若需按域名或请求头区分,应改用 map 指令。
通过 map 将分组映射为限速数值
limit_rate 不接受变量直接赋值(Nginx ≤ 1.17.7),所以要用 map 把 $user_group 转成具体字节数(单位:bytes/second):
http {
geo $user_group { ... }
<pre class="brush:php;toolbar:false;">map $user_group $limit_rate_value {
default 262144; # 256K = 256 * 1024
"cn" 1048576; # 1M = 1024 * 1024
"isp_a" 2097152; # 2M
"overseas" 524288; # 512K
}}
这样就得到了可被 limit_rate 引用的整数变量 $limit_rate_value。
在 location 中启用动态限速
把 limit_rate 放在需要限速的 location 块中,并使用变量值:
server {
listen 80;
server_name example.com;
<pre class="brush:php;toolbar:false;">location /download/ {
limit_rate $limit_rate_value;
# 可选:下载前允许高速缓冲一段(例如前 5MB 不限速)
limit_rate_after 5m;
# 静态文件服务
root /data/files;
try_files $uri =404;
}}
-
limit_rate_after配合limit_rate使用,实现“先快后慢”,提升小文件体验 - 变量值为 0 表示不限速;设为 1 表示极低速(1 byte/s),可用于临时封禁
- 该配置对每个连接独立生效,不影响并发连接数限制
验证与调试技巧
限速是否生效可通过以下方式确认:
- 用
curl -v http://example.com/download/big.zip --limit-rate 0对比下载速度 - 在
log_format中加入$user_group和$limit_rate_value,查看实际匹配结果 - 使用不同 IP(如代理或云主机)访问,检查响应头中的
X-Response-Time或日志字段是否变化 - 注意:浏览器多线程下载可能绕过单连接限速,建议配合
limit_conn控制并发连接数


















