一、示例配置
http {
# 定义一个名为 one 的限速区域,10MB 内存,平均速率 1 请求/秒
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
listen 80;
server_name example.com;
location /search/ {
# 使用 one 区域,允许突发最多 5 次请求,超出的请求会排队延迟处理
limit_req zone=one burst=5;
}
}
}
二、指令详解
1. limit_req_zone
-
语法
limit_req_zone <key> zone=<name>:<size> rate=<rate> [sync];
-
上下文:
http
-
必需参数
<key>
:限速键,通常包含变量(如$binary_remote_addr
)。zone=<name>:<size>
:共享内存区域名称及大小(如zone=one:10m
)。rate=<rate>
:平均允许速率,单位r/s
(请求/秒)或r/m
(请求/分钟),如1r/s
、30r/m
。
-
可选参数
sync
(1.15.3+,仅商业版):开启多 worker 进程间限速状态同步。
-
默认:无
-
说明
- 每个 key 在共享内存中占用固定字节(32 位平台 64B,64 位平台 128B),10MB 区域大约可保存
<size> * 1024*1024 / bytes_per_state
条记录。 - 区域满时淘汰最久未使用状态,若仍不能创建新状态,则直接拒绝请求。
- 每个 key 在共享内存中占用固定字节(32 位平台 64B,64 位平台 128B),10MB 区域大约可保存
-
示例
# 每个 IP 平均 1r/s,区域 one 大小 10MB limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
2. limit_req
-
语法
limit_req zone=<name> [burst=<number>] [nodelay | delay=<number>];
-
上下文:
http, server, location
-
参数
zone=<name>
:指定前面定义的限速区域名称。burst=<number>
(默认0
):允许的最大突发请求数(桶大小)。delay=<number>
(1.15.7+,默认0
):超过平均速率时可延迟的最大请求数,超过该值即拒绝。nodelay
:不延迟,超出突发数即刻拒绝。
-
默认:无
-
说明
- 突发处理:在不超过
burst
时,允许短期内突发放行;超过后依旧按照平均速率放行或拒绝。 nodelay
与delay
互斥,nodelay
会使任何超过burst
的请求直接返回错误码(可由limit_req_status
指令指定)。
- 突发处理:在不超过
-
示例
# 允许平均 1r/s,突发最多 5 次,超出突发立即拒绝 limit_req zone=one burst=5 nodelay; # 允许平均 1r/s,突发最多 5 次,超出突发但小于 delay 时延迟处理 limit_req zone=one burst=5 delay=10;
3. limit_req_dry_run
-
语法
limit_req_dry_run on | off;
-
上下文:
http, server, location
-
启用版本:1.17.1+
-
默认:
off
-
说明
- 干运行模式:不实际限速,只记录“过量”请求在共享内存中的计数,便于评估配置效果而不影响正常流量。
-
示例
limit_req zone=one burst=5; limit_req_dry_run on;
4. limit_req_log_level
-
语法
limit_req_log_level info | notice | warn | error;
-
上下文:
http, server, location
-
启用版本:0.8.18+
-
默认:
error
-
说明
- 设置拒绝(REJECTED)及延迟(DELAYED)请求的日志级别。
- 延迟事件级别比拒绝事件低一级(如
notice
配置下,延迟记录为info
)。
-
示例
limit_req_log_level notice;
5. limit_req_status
-
语法
limit_req_status <code>;
-
上下文:
http, server, location
-
启用版本:1.3.15+
-
默认:
503
-
说明
- 当请求被拒绝(超过突发且非 dry-run)时返回的 HTTP 状态码。
-
示例
limit_req_status 429; # 超速时返回 429 Too Many Requests
三、嵌入变量
-
$limit_req_status
(1.17.6+)
该变量记录本次请求的限速结果,可能的取值:PASSED
DELAYED
REJECTED
DELAYED_DRY_RUN
REJECTED_DRY_RUN
可在日志格式或后续脚本中引用,例如:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$limit_req_status"';
四、实现原理与注意事项
-
“漏桶”算法
- 每个 key 对应一个“桶”,按照固定速率漏出请求令牌;突发请求可瞬时消耗桶内的额外容量(burst)。
- 超出 burst 后的请求,若设置了
delay
,则在令牌不可用时排队等待;若未设置或nodelay
,则直接拒绝。
-
状态管理
- 限速状态保存在共享内存,支持多 worker 进程共享;商业版可开启
sync
实现跨机同步。 - 区域大小与 key 数量需平衡:区过小会导致频繁 LRU 淘汰,大区则浪费内存。
- 限速状态保存在共享内存,支持多 worker 进程共享;商业版可开启
-
配置继承
limit_req
系指令可置于http
、server
、location
三级;若某级别未显式配置,则继承父级。
-
干运行(dry run)
- 在流量高峰或生产环境初次调优时,可先启用
limit_req_dry_run
,仅记录限速,无实际影响。
- 在流量高峰或生产环境初次调优时,可先启用
-
状态暴露(商业版)
- 从 1.17.7 起,商业版可通过 API 查看或重置共享内存区的统计信息,便于运维监控与排查。
五、总结
ngx_http_limit_req_module
通过灵活的突发控制与延迟/拒绝策略,为 Nginx 提供了高效的流量限速能力。结合 dry-run、日志级别与内置变量,可在保证服务可用性的同时,抵御突发或恶意请求。