nginx 限速:那几个参数到底在限制什么
limit_req 的参数看起来很简单,但 rate 和 burst 的关系大多数人第一次都理解反了。这篇用一个例子讲清楚。
先定义,再解释
limit_req_zone $binary_remote_addr zone=blog_req:10m rate=5r/s;
server {
location / {
limit_req zone=blog_req burst=30 nodelay;
limit_req_status 429;
}
}
rate=5r/s:补充速度,不是上限。每 200ms 往桶里放一个令牌。burst=30:桶的容量,最多能攒 30 个令牌。nodelay:攒着的令牌可以一次性用掉,不排队。
所以真实上限是:短时间内最多 burst 个请求直接放行,之后按 rate 的速度慢慢恢复。
算一遍
rate=5r/s + burst=30:
- 第 1 秒来了 30 个请求 → 全部放行(30 个令牌瞬间用完)
- 接着来了 40 个 → 按每秒 5 个的速度恢复,能过几个是几个,其余 429
- 安静 6 秒 → 桶重新攒满 30 个
如果去掉 nodelay,那 30 个令牌会变成"排队等待",请求会变慢但不报错。对网页来说排队伤害体验,对脚本来说排队等于没挡,所以静态站一律 nodelay。
参数怎么定
单个页面加载大概是 1 个 HTML + 3–6 个静态资源,浏览器并发 6。真人一分钟最多也就几十个请求。
我的经验值:
| 站类型 | rate | burst |
|---|---|---|
| 静态博客 | 5r/s | 30 |
| 带 API 的站 | 5r/s | 40–60 |
| 下载站 | 10r/s | 20(别太大) |
burst 给得太大等于没限速,给得太小正常用户会被误伤。测的时候用 20 并发打 60 次,看 429 的比例在 10%–40% 之间比较合理。
为什么你的限速不生效
三个高频原因,按出现频率排:
一、zone 写在 server 里。 limit_req_zone 必须写在 http 级,放 server 或 location 里 nginx -t 会报错。
二、挂了 CDN 没做 realip。 $binary_remote_addr 全是 CDN 节点地址,所有访客共用一个桶。表现是"一个人触发限速,全站跟着 429",比不限速更糟。
三、limit_req 和 limit_conn 搞混。 前者限速率,后者限并发连接数。慢速攻击(一个连接慢慢发)要靠 limit_conn,快速 CC 要靠 limit_req,两个都要有。
limit_req_status 默认是 503。很多人以为是限速没生效,其实是代码在测 429 而服务器返 503。显式写一行 limit_req_status 429; 省很多排查时间。
验证
# 20 并发打 60 次,看状态码分布
seq 1 60 | xargs -P20 -I{} curl -s -o /dev/null -w '%{http_code}\n' \
https://你的站/ | sort | uniq -c
正常应该看到一批 200 加一批 429。全是 200 说明阈值太宽,全是 429 说明第一层就被误伤——先查 realip。
需要按上面的步骤在自己服务器上配一遍? 可以邮件 2725854295@qq.com,或者关注公众号「凌的科技圈」留言。说明系统版本和域名,我给一套现成的配置文件。