Nginx频率门控本质是限制客户端到Nginx的请求频次,而非Nginx到后端的调用频次;需分单机限流(limit_req_zone)和集群全局限流(Redis+Lua)两层实现,并可结合后端状态动态调整限速值。

在 Nginx 中对后端集群节点做访问频率门控,本质不是限制“Nginx 到后端”的调用频次,而是限制**客户端到 Nginx 的请求频次**,再由 Nginx 均匀或按策略转发给后端集群。Nginx 本身不直接感知后端节点的负载或状态来做动态频控;真正的“集群级门控”需分两层实现:单机限流 + 全局协调。
单节点基础限流:用 limit_req_zone 控制入口流量
这是最常用、最轻量的方式,适用于中小规模或同构集群:
-
定义限流规则:在
http{}块中声明一个共享内存区域,例如按 IP 限速:
其中 perip 是规则名,10m 表示最多存约 8 万个 IP 状态,50r/s 是每秒允许请求数。
- 在 location 或 server 中启用:比如保护 API 接口:
limit_req zone=perip burst=100 nodelay;
proxy_pass http://backend_cluster;
}
burst=100 允许瞬时积压 100 个请求,nodelay 表示这些请求不排队、立即转发(但计数仍受 rate 约束)。
集群全局限流:必须借助 Redis + Lua(OpenResty)
当多台 Nginx 实例共用一套后端集群时,单机限流会失效——同一 IP 可能被不同 Nginx 节点重复计数。此时需外部统一计数器:
- 安装 OpenResty(含 Lua 和 redis.lua 库),确保支持
access_by_lua_file阶段; - 在
http{}中配置 Redis 连接池和超时降级逻辑; - 编写 Lua 脚本:提取
$binary_remote_addr或自定义 key(如加 User-Agent 标识爬虫),执行 INCR + EXPIRE 原子操作,判断是否超限; - 超限时返回 429,并可选写入临时封禁列表;失败时自动 fallback 到本地 limit_req,避免雪崩。
典型 key 设计:rate:ip:192.168.1.100:20260606(带日期分片防 key 过大),TTL 设为略大于窗口时间(如 65 秒限 60 秒窗口)。
按后端服务能力反向设限:基于 upstream 状态动态调整
如果后端集群自身提供健康度指标(如 Prometheus 暴露的 QPS、延迟、错误率),可通过以下方式联动限流:
- 用 Nginx Plus 的
status模块或自建 health check 接口定期拉取后端负载数据; - 结合 map 指令映射动态限速值,例如:
1 "10r/s";
0 "100r/s";
}
limit_req_zone $binary_remote_addr zone=adaptive:10m rate=$dynamic_rate;
注意:该方案需 Nginx Plus 或配合第三方模块(如 nginx-http-sysguard),开源版需用 Lua 手动实现类似逻辑。
补充防护:封禁+日志+可观测性
频率门控不是孤立动作,需配套落地:
- 用
deny/allow快速封禁已确认恶意 IP; - 设置
limit_req_status 429和limit_req_log_level warn,便于 ELK 或 Loki 聚合分析异常模式; - 开启
stub_status或 Prometheus Exporter,监控limiting requests计数器,验证门控是否生效。
不复杂但容易忽略


















