返回

Nginx 如何限制单个 IP 请求频率?limit_req 实战配置

2026-09-30 Nginx 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。

顶部