直接在目标接口location块中配置limit_req并用=精确匹配路径,可实现单接口精准限流;按$uri定义限流区域、合理设置burst/nodelay、返回429并记录$limit日志,确保限流准确可控。

直接在目标接口的 location 块里配 limit_req,配合 limit_req_zone 定义,就能实现单接口精准限流。
关键不是加在哪里,而是怎么匹配、怎么定义、怎么控制行为。
用精确匹配锁定单一接口
别用前缀匹配(比如 location /api/),否则 /api/v1/order 和 /api/v1/user 全被框住。要用 = 实现完全相等匹配:
location = /api/v1/order {
limit_req zone=order_limit burst=8 nodelay;
proxy_pass http://backend;
}
这样只有 GET /api/v1/order HTTP/1.1 这种完整路径才触发限流,其他路径不受影响。
按接口路径定义限流区域
限流要“按接口分桶”,不能只按 IP。在 http 块里这样写:
limit_req_zone $uri zone=order_limit:10m rate=3r/s;
-
$uri只取路径部分(不含 query string),所以/api/v1/order?id=123和/api/v1/order?token=abc都算同一个接口; -
rate=3r/s表示该接口每秒最多放行 3 个请求; -
10m内存足够存几万个不同 URI 的状态,够用。
控制突发和响应方式
burst 和 nodelay 组合决定流量怎么“削峰”:
-
burst=8 nodelay:允许最多 8 个请求立刻通过,超了就直接返回 429; -
burst=8(不加 nodelay):超出速率的请求会排队,按每秒 3 个匀速放行,延迟升高但更平滑; -
burst=0或省略 burst:严格卡死速率,连瞬时抖动都不放——适合核心下单、支付类接口。
返回码和日志要能定位问题
默认返回 503 不利于前端识别,加上这句:
limit_req_status 429;
再在 log_format 中加入 $limit 变量:
log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $limit';
日志里就能看到哪条请求命中了 order_limit 区域,方便排查是否误配或被刷。
不复杂但容易忽略











