Nginx 如何限制单个 IP 请求频率?limit_req 实战配置
2026-09-30 2 0
Nginx 自带 ngx_http_limit_req_module,可以按照客户端 IP、请求参数等 Key 统计请求频率。限制单个 IP 时,通常使用 $binary_remote_addr 作为 Key。Nginx 官方文档采用的也是这种配置方式。
1. 最基本的限流配置
在 http 配置段添加:
http {
limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=2r/s;
server {
listen 80;
server_name example.com;
location / {
limit_req zone=ip_limit;
}
}
}
这里有三个关键参数:
$binary_remote_addr 表示客户端 IP。相比 $remote_addr,二进制形式占用的共享内存更少。
zone=ip_limit:10m 创建一个 10 MB 的共享内存区域,用于保存不同 IP 的限流状态。
rate=2r/s 表示平均每个 IP 每秒允许处理 2 个请求。rate 也可以使用 r/m,例如 60r/m。
2. burst 处理短时间突发请求
实际网站经常出现短时间连续请求。例如页面加载时,浏览器可能在很短时间内请求多个 CSS、JS 和接口。如果严格限制为 2r/s,用户体验可能受到影响。
可以增加 burst:
limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=2r/s;
server {
location /api/ {
limit_req zone=ip_limit burst=10;
}
}
burst=10 表示允许额外的突发请求进入队列。超过设定速率的请求会被延迟处理,队列超过 10 个请求后,新的请求会被拒绝。默认拒绝状态码是 503。
3. burst 配合 nodelay
如果接口对响应延迟比较敏感,可以使用:
limit_req zone=ip_limit burst=10 nodelay;
这种情况下,处于 burst 范围内的请求会立即处理,不会按照 rate 排队等待。超过 burst 数量的请求才会被拒绝。
例如登录接口可以这样配置:
location /login {
limit_req zone=ip_limit burst=5 nodelay;
proxy_pass http://backend;
}
4. API 接口的常见配置
对于普通 API,可以采用比较温和的限制:
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s;
server {
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://backend;
}
}
含义是单个 IP 平均每秒允许 5 个请求,同时允许短时间出现 20 个突发请求。实际参数需要结合接口响应速度、正常访问量和业务特点调整。
5. 修改超限后的状态码
Nginx 默认使用 503 Service Unavailable 表示请求被限流,也可以改成其他状态码:
limit_req_status 429;
完整配置:
http {
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s;
server {
location /api/ {
limit_req zone=api_limit burst=10 nodelay;
limit_req_status 429;
proxy_pass http://backend;
}
}
}
对于 API,返回 429 Too Many Requests 通常更容易让客户端理解当前请求触发了频率限制。limit_req_status 可以自定义拒绝请求的响应状态码。
6. 配置后如何测试
修改 Nginx 配置后先检查:
nginx -t
确认没有错误,再重新加载:
nginx -s reload
测试接口可以连续发送请求:
for i in {1..30}; do curl -I https://example.com/api/test; done
如果担心直接启用限流影响线上用户,可以先使用 limit_req_dry_run on;。该模式会统计超额请求并记录日志,但不会真正限制请求。
实际部署时,建议把严格限流放在登录、验证码、搜索、API 等容易被频繁调用的路径,不必对整个网站设置过低的请求频率。若 Nginx 位于 CDN 或反向代理之后,还需要确认客户端真实 IP 的获取方式,否则 $binary_remote_addr 可能记录的是代理服务器 IP,导致大量用户共享同一个限流 Key。