Nginx可通过geo模块标记客户端区域,再结合limit_req_zone的复合key(如$client_area$binary_remote_addr)或map映射动态rate,实现按国内、海外、白名单等差异化限速;需注意default必须设置、旧版本不支持rate变量、避免在if中用limit_req。

在 Nginx 中,通过 limit_req 模块配合 geo 模块,可以为不同来源的客户端(如国内、海外、特定 IP 段)设置差异化的请求速率限制策略。核心思路是:用 geo 定义变量标记客户端所属区域或类型,再将该变量作为 limit_req_zone 的 key,实现按需分区限速。
一、用 geo 模块划分客户端群体
geo 指令用于根据客户端 IP 生成自定义变量,值可为字符串、数字或空(未匹配)。注意它只支持 IPv4 精确匹配或 CIDR,不支持域名或正则;若需更灵活识别(如国家/地区),建议前置部署 GeoIP2 或使用第三方模块。
示例:区分国内(CN)、海外(OTHER)及白名单(WHITELIST)
geo $client_area {
default OTHER;
127.0.0.1 WHITELIST;
192.168.0.0/16 WHITELIST;
114.114.114.114 CN;
include /etc/nginx/conf.d/cn-ips.conf; # 包含中国公网 IP 段列表
}
关键点:
-
default必须存在,否则未匹配 IP 会触发变量未定义错误 - IP 段文件(如
cn-ips.conf)每行一条 CIDR,格式如202.96.0.0/16 CN; - 变量名(如
$client_area)将在后续limit_req_zone中引用
二、为不同区域定义独立限速区
limit_req_zone 的 key 支持复合变量,可结合 $client_area 构建多区域限速桶。每个区域对应独立内存 zone,互不影响。
limit_req_zone $binary_remote_addr zone=global:10m rate=10r/s; limit_req_zone $binary_remote_addr zone=cn:10m rate=50r/s; limit_req_zone $binary_remote_addr zone=whitelist:10m rate=200r/s;
但上述写法无法直接关联 $client_area —— 正确做法是让 key 包含区域标识:
limit_req_zone $client_area$binary_remote_addr zone=by_area:20m rate=30r/s;
这样,"CN" + IP、"WHITELIST" + IP、"OTHER" + IP 被视为不同 key,各自拥有独立计数器。再通过 map 映射不同区域的实际限速值(更推荐):
map $client_area $area_rate {
default "10r/s";
CN "60r/s";
WHITELIST "300r/s";
}
limit_req_zone $binary_remote_addr zone=per_ip:20m rate=$area_rate;
⚠️ 注意:rate= 后不支持变量直接展开(Nginx 1.13.8+ 支持),旧版本需用 map + 多 zone 方式模拟。
三、在 server 或 location 中启用限速
使用 limit_req 指令绑定 zone,并可配置突发容量(burst)与是否延迟(nodelay)。
server {
listen 80;
server_name api.example.com;
<pre class='brush:php;toolbar:false;'>location /api/ {
# 根据区域选择对应 zone(若用 map + 单 zone)
limit_req zone=per_ip burst=20 nodelay;
# 或按区域分别应用(兼容老版本)
# if ($client_area = "CN") { limit_req zone=cn burst=50 nodelay; }
# if ($client_area = "WHITELIST") { limit_req zone=whitelist burst=100 nodelay; }
# if ($client_area = "OTHER") { limit_req zone=global burst=5 nodelay; }
proxy_pass http://backend;
}}
说明:
-
burst允许短时突发请求数,超出部分将被延迟或拒绝(取决于是否加nodelay) - 避免在
if中使用limit_req(Nginx 官方不推荐),优先采用map+ 动态 rate 或复合 key zone - 测试时可用
curl -I http://your-domain/api/test查看响应头中的X-RateLimit-Limit和X-RateLimit-Remaining(需自行添加 header)
四、验证与调试技巧
限速策略上线前务必验证逻辑是否生效:
- 用不同 IP(或修改本地 hosts + curl 指定
--resolve)模拟各区域请求 - 检查 error.log 中是否有
limiting requests日志(开启error_log /path/to/error.log info;) - 用
nginx -t确保配置语法正确,reload 后用nginx -s reload - 监控
stub_status(需编译时启用)或 Prometheus + nginx-vts-exporter 观察各 zone 的当前请求数
常见问题:geo 变量为空导致限速失效 → 检查 IP 是否匹配、default 是否设置;rate 值未生效 → 确认 Nginx 版本是否支持变量 rate,否则改用多 zone + if(临时方案)或升级。


















