Nginx 基于请求频率的 API 限流需精准定义 key(如 X-Api-Key 或 JWT 解析的 sub)、在 proxy_pass 前启用 limit_req、差异化配置 burst/nodelay、返回 429 JSON 响应,并联动 upstream 健康检查。

在 Nginx 中配置基于请求频率的 API 访问限制,核心是用好 limit_req 模块,结合合理 key 定义与 upstream 协同,而不是简单按 IP “一刀切”。关键在于区分真实调用者、控制突发流量、返回友好错误,并确保限流生效位置正确。
定义精准的限流标识区域
避免只用 $binary_remote_addr(IP)限流,容易误伤 NAT 环境下的合法用户。应优先提取请求身份标识:
- 若客户端带
X-Api-Key头,直接用它作为 key:limit_req_zone $http_x_api_key zone=api_perkey:10m rate=20r/s; - 若使用 JWT 认证,需配合 Lua 模块(如
lua-resty-jwt)解析 token,提取sub或client_id并赋值给变量,再用于 zone 定义 - 如需兜底防护,可额外定义宽松的 IP 限流:
limit_req_zone $binary_remote_addr zone=api_perip:10m rate=100r/m;
在 proxy_pass 前启用限流规则
限流必须放在 location 块中、且严格位于 proxy_pass 指令之前,否则请求已转发至后端,限流就失效了:
- 对不同 API 路径设置差异化限流,例如:
location /v1/pay { limit_req zone=api_perkey burst=5 nodelay; proxy_pass http://backend-pay; } -
burst=5表示允许最多 5 个请求排队等待处理,缓解短时高峰 -
nodelay表示 burst 内的请求不延迟、立即处理;若去掉,则超限请求会被匀速释放(漏桶行为更明显)
返回标准、可读的限流响应
默认 503 不适合 API 场景,应统一返回 429 并附带 JSON 提示:
- 用
limit_req_status 429修改状态码 - 搭配
error_page自定义响应体:error_page 429 = @rate_limited;<br>location @rate_limited {<br> add_header Content-Type "application/json";<br> return 429 '{"error":"rate_limit_exceeded","retry_after":60}';<br>} - 可选:加
limit_req_log_level warn记录被拒详情,方便定位高频调用来源
联动 upstream 实现稳定分发
限流本身不干预负载逻辑,但需与后端健康状态协同:
- 确保
upstream配置启用基础健康检查(如health_check)和重试机制:proxy_next_upstream error timeout http_500; - 被限流的请求不会进入 upstream,因此无需在 upstream 中做限流适配
- 灰度上线时,先对非核心接口开启,通过
stub_status或 Prometheus 监控limit_req的拒绝计数,确认规则符合预期


















