limit_req_zone 是限流核心指令,定义共享内存区域实现漏桶算法限速;它不直接管控缓存,但可通过 map 构建业务键、结合 limit_req_status 与 proxy_cache_bypass 实现差异化限流,间接优化缓存效率。

limit_req_zone 本身不用于缓存管控,它是限流模块的核心指令,作用是定义请求频率限制的共享内存区域,基于漏桶算法控制请求速率。它和缓存(如 proxy_cache)属于不同机制:一个管“进来的速度”,一个管“是否复用已有的响应”。
但你可以结合自定义变量 + limit_req_zone + 其他模块(如 map、if、proxy_cache_bypass),间接实现“按业务逻辑差异化限流”,从而影响缓存命中与压力分布——这常被误称为“高级缓存管控”,实际是通过限流策略引导缓存使用效率。
下面分三块讲清楚怎么做:
✅ 一、用 map 构建业务维度的限流键
Nginx 不允许在 limit_req_zone 中直接写复杂表达式,但可以用 map 预计算变量,再引用:
http {
# 根据请求头、参数、路径等提取业务标识
map $request_uri $biz_key {
~^/api/v1/order/create$ "order_create";
~^/api/v1/product/detail\?id=(\d+) "product_$1";
~^/api/v1/user/profile "user_profile";
default "other";
}
# 基于业务键做限流(注意:key 要尽量简短,避免内存浪费)
limit_req_zone $biz_key zone=biz_limit:10m rate=5r/s;
}
这样,下单接口、商品详情、用户资料就各自走独立的限流桶,不会互相干扰,也便于后续观察各业务线的请求毛刺。
✅ 二、配合 limit_req 和 proxy_cache_bypass 控制缓存行为
限流本身不干预缓存,但你可以让“被限流的请求”绕过缓存,强制打到后端(用于调试或降级),而正常请求走缓存:
server {
location /api/ {
# 应用业务限流
limit_req zone=biz_limit burst=3 nodelay;
# 若触发限流($limit_req_status == "rejected" 或 "delayed"),跳过缓存
set $skip_cache 0;
if ($limit_req_status = "rejected") {
set $skip_cache 1;
}
if ($limit_req_status = "delayed") {
set $skip_cache 1;
}
proxy_cache_bypass $skip_cache;
proxy_no_cache $skip_cache;
proxy_cache cache_one;
proxy_pass http://backend;
}
}
⚠️ 注意:$limit_req_status 是 Nginx 1.13.6+ 内置变量,值为 passed / delayed / rejected,可直接用于条件判断。
✅ 三、按用户等级或设备类型动态调整限流强度
比如 VIP 用户放宽限制,爬虫或低版本 App 严格限速:
map $http_user_agent $user_tier {
~*android.*version/1\.2 "low";
~*weibo "crawler";
~*vip=true "vip";
default "normal";
}
map $user_tier $rate_limit {
"vip" "20r/s";
"normal" "5r/s";
"low" "2r/s";
"crawler" "1r/m"; # 极严
}
# ❌ 错误:不能在 limit_req_zone 中用变量代替 rate
# limit_req_zone $binary_remote_addr zone=user_rate:10m rate=$rate_limit;
# ✅ 正确:用多个预定义 zone + 条件选择
limit_req_zone $binary_remote_addr zone=vip_rate:10m rate=20r/s;
limit_req_zone $binary_remote_addr zone=normal_rate:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=low_rate:10m rate=2r/s;
limit_req_zone $binary_remote_addr zone=crawler_rate:10m rate=1r/m;
server {
location /api/ {
# 按 tier 选择对应 zone
if ($user_tier = "vip") {
limit_req zone=vip_rate burst=10 nodelay;
}
if ($user_tier = "normal") {
limit_req zone=normal_rate burst=5;
}
if ($user_tier = "low") {
limit_req zone=low_rate burst=2;
}
if ($user_tier = "crawler") {
limit_req zone=crawler_rate burst=1 nodelay;
}
proxy_pass http://backend;
}
}
? 提示:
if在location中可用,但不要嵌套或滥用;更健壮的做法是用 OpenResty 或 Lua 实现动态 zone 调度,不过纯 Nginx 场景下上述方式已覆盖大多数业务需求。
不复杂但容易忽略










