---
id: nginx-limit-req
title: nginx 限速：那几个参数到底在限制什么
date: 2025-12-11
updated: 2026-09-20
category: 建站
tags: nginx, 限速
minutes: 7
---

`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。
