Nginx 限流:limit_req 与 limit_conn 的分工
发布时间:2026-10-07 12:13       
更新时间:2026-10-08 10:40
登录接口被脚本刷、爬虫把带宽吃满,这类问题在请求到达应用之前就该有一道闸。Nginx 自带两个限流模块:limit_req 按请求频率限制,limit_conn 按并发连接数限制,两者管的不是一回事,经常配合使用。
一、limit_req:管频率
先在 http 段定义一个限流区:
```
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
```
$binary_remote_addr 表示按客户端 IP 计,rate=10r/s 即每秒允许 10 个请求。底层是令牌桶算法:按恒定速率往桶里放令牌,请求拿到令牌才能过,拿不到就排队或拒绝。突发流量在桶容量范围内可以被吸收,这是它比硬计数平滑的地方。
二、burst 与 nodelay
```
location /api/login/ {
limit_req zone=perip burst=20 nodelay;
}
```
burst=20 表示额外允许 20 个突发请求。不加 nodelay,超出的请求被延后处理,用户感受是页面转圈;加 nodelay 则立即处理这 20 个,再多直接拒绝。前端一次并发拉十几个接口的页面,不给 burst 会误伤正常用户,这是限流误报的头号原因。
三、limit_conn:管并发
```
limit_conn_zone $binary_remote_addr zone=connperip:10m;
location /download/ {
limit_conn connperip 5;
}
```
含义是单个 IP 对这个 location 最多同时 5 个连接。下载站、文件服务用它防止单点吃满带宽,效果比限频率更直接。
四、怎么分工
- 刷接口、撞库:limit_req 为主,阈值参考正常用户的操作间隔。
- 大文件下载、流媒体:limit_conn 为主。
- 全站兜底:http 段放一个宽松的 limit_req,敏感 location 上再收紧。
被拒请求默认返回 503,用 limit_req_status 429 改成语义更准的 429 Too Many Requests。内网办公出口被误伤时,用 geo 模块定义白名单变量,放进 limit_req_zone 的键里,公司出口 IP 直接不参与计数。两个认知边界:限流计数放在 Nginx 内存里,重启即清零,它防的是瞬时滥用,不是持久对抗;同一 IP 背后可能是一个 NAT 出口的上百名真实用户,阈值定得太紧会成片误伤。
阈值别拍脑袋定。先从访问日志统计正常用户峰值:
```
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head
```
留出一倍余量再上线,灰度观察 error.log 里的 limiting requests 记录,被限的请求都会在这里留下 IP 和触发的规则名,据此调阈值比拍脑袋准得多,误伤多了再放。