Nginx ~ 限流
nginx
DNS / CDN
↓
Nginx 网关限流(第一道门)
↓
API 网关限流(第二道门)
↓
服务内部限流(第三道门)
↓
数据库连接池一、Nginx 限流的两个核心模块
Nginx 限流主要靠两个模块:
✅ 1. 请求频率限流(QPS)
模块:limit_req_module 控制:单位时间请求次数
✅ 2. 连接数限流
模块:limit_conn_module 控制:同时连接数
二、请求频率限流(limit_req)
✅ 基本语法结构
1️⃣ 定义限流规则(http 块)
nginx
http {
## 定义一个共享内存区,按 IP 限流
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=10r/s;
}解释:
$binary_remote_addr:按客户端 IPzone=req_limit_per_ip:10m:分配 10MB 内存rate=10r/s:每秒最多 10 个请求
2️⃣ 应用到接口(server 或 location)
nginx
server {
listen 80;
server_name api.example.com;
location /api/ {
limit_req zone=req_limit_per_ip burst=20 nodelay;
proxy_pass http://backend;
}
}参数说明:
burst=20:允许瞬间突发 20 个请求nodelay:不排队,超过直接拒绝- 默认返回:
429 Too Many Requests
✅ 常见限流组合示例
🌟 场景 1:登录接口限流
nginx
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
server {
location /login {
limit_req zone=login burst=3 nodelay;
proxy_pass http://auth_service;
}
}含义:
每个 IP 每分钟最多 5 次登录请求
🌟 场景 2:按用户 ID 限流(更精准)
nginx
limit_req_zone $arg_userId zone=user_limit:10m rate=20r/m;URL:
/api/order?userId=123🌟 场景 3:全站总流量限流
nginx
limit_req_zone $server_name zone=global:20m rate=2000r/s;
location / {
limit_req zone=global burst=500;
}🌟 场景 4:防爬虫(UA + IP)
nginx
map $http_user_agent $is_bot {
default 0;
~*curl 1;
~*python 1;
~*spider 1;
}
limit_req_zone $binary_remote_addr zone=bot:10m rate=2r/s;
server {
location / {
if ($is_bot) {
limit_req zone=bot burst=2 nodelay;
}
proxy_pass http://backend;
}
}三、连接数限流(limit_conn)
限制同时连接数(防止占满资源)
1️⃣ 定义连接限制
nginx
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;2️⃣ 使用
nginx
location /api/ {
limit_conn conn_limit_per_ip 5;
proxy_pass http://backend;
}含义:
每个 IP 同时最多 5 个连接
四、组合限流(请求数 + 连接数)
nginx
http {
limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn:10m;
}
server {
location /api/ {
limit_req zone=req burst=20 nodelay;
limit_conn conn 5;
proxy_pass http://backend;
}
}双保险。
五、返回自定义限流提示页面
nginx
location /api/ {
limit_req zone=req burst=10;
error_page 429 = /limit.html;
}
location = /limit.html {
return 200 "访问过于频繁,请稍后再试";
}六、限流日志记录(便于监控)
nginx
log_format limit_log '$remote_addr $request_time $status';
access_log /var/log/nginx/limit.log limit_log;七、分布式限流(Redis + Lua,OpenResty)
如果多台 Nginx:
lua
local key = ngx.var.binary_remote_addr
local redis = require "resty.redis"
local r = redis:new()
r:connect("127.0.0.1", 6379)
local count = r:incr(key)
if count == 1 then
r:expire(key, 1)
end
if count > 10 then
ngx.exit(429)
endNginx 配置:
nginx
location /api/ {
access_by_lua_file /etc/nginx/lua/limit.lua;
proxy_pass http://backend;
}八、限流调优参数建议表
| 场景 | rate | burst |
|---|---|---|
| 登录接口 | 5r/m | 2 |
| 下单接口 | 10r/s | 5 |
| 查询接口 | 50r/s | 20 |
| 爬虫 | 1r/s | 1 |
| 全站 | 2000r/s | 500 |
九、限流常见坑
❌ burst 太小 → 正常用户被挡 ❌ rate 太大 → 形同虚设 ❌ 没监控 → 不知道限了谁 ❌ 所有接口同一策略 → 业务崩
十、完整企业级示例配置(可直接用)
nginx
http {
limit_req_zone $binary_remote_addr zone=api_limit:20m rate=20r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:20m;
server {
listen 80;
location /api/ {
limit_req zone=api_limit burst=40 nodelay;
limit_conn conn_limit 10;
error_page 429 = /limit.json;
proxy_pass http://backend;
}
location = /limit.json {
default_type application/json;
return 200 '{"code":429,"msg":"请求过于频繁"}';
}
}
}十一、一句话总结 Nginx 限流原理 + 实现
Nginx 限流 = 共享内存计数 + 令牌桶算法 + key 维度(IP/用户) + 规则判断 + 直接拒绝请求
