Nginx可通过limit_req_zone和limit_req实现单IP每秒请求数限制,基于$binary_remote_addr定义令牌桶限流区域,配合burst和nodelay控制突发请求处理策略,并需注意真实IP提取与日志验证。

直接在 Nginx 配置中用 limit_req_zone 和 limit_req 就能实现单 IP 每秒最大请求数限制,核心是基于客户端真实 IP 做令牌桶或漏桶式限流,防接口被高频刷取。
定义限流区域(必须放在 http 块内)
在 http{...} 中添加如下配置:
-
$binary_remote_addr是最常用且省内存的键,表示客户端 IPv4/IPv6 地址的二进制形式(比$remote_addr节省约 60% 内存) -
zone=myip:10m表示开辟 10MB 共享内存存储每个 IP 的计数器;10MB 约支持 16 万个独立 IP 记录 -
rate=5r/s表示每秒最多放行 5 个请求(Nginx 实际按毫秒级精度控制,即每 200ms 最多处理 1 个)
示例:
http {limit_req_zone $binary_remote_addr zone=myip:10m rate=5r/s;
}
在目标 location 中启用限流
把限流规则应用到具体路径,比如登录、API 接口等易被攻击的入口:
-
limit_req zone=myip burst=10:允许突发 10 个请求缓存排队,超出部分按漏桶逻辑延迟处理 - 加
nodelay可让突发请求不排队,直接拒绝并返回 503,适合防暴力破解场景 - 若希望对特定接口(如
/api/v1/login)单独限流,就把limit_req放在对应location块里
示例:
location /api/v1/login {limit_req zone=myip burst=5 nodelay;
proxy_pass http://backend;
}
关键细节与避坑点
实际生效依赖几个隐含条件:
- 确保后端服务未透传代理 IP —— 若用 CDN 或负载均衡,需通过
X-Forwarded-For提取真实 IP,并用set_real_ip_from+real_ip_header配合,否则限流对象会变成代理 IP -
burst不是“额外额度”,而是缓冲队列长度;配合nodelay才真正实现“超了就拒”,否则请求会排队等待,可能掩盖真实过载 - 日志中可通过
limit_req_log_level error开启限流拒绝记录,再配合log_format输出$limit_req_status字段,便于识别 503 来源
验证与调优建议
上线前建议做两件事:
- 用
ab -n 100 -c 20 http://yourdomain/api/login模拟并发压测,观察返回状态码分布和响应时间变化 - 初期可设宽松值(如
rate=10r/s),再根据访问日志中$limit_req_status的rejected出现频率逐步收紧 - 避免对静态资源(如 CSS/JS)误限流,应将
limit_req仅放在业务接口路径下


















