nginx原生不支持集群限流,因其limit_req_zone等模块依赖本地共享内存,无法跨机器同步状态;必须借助redis或统一网关(如apisix)等外部组件实现全局限流。

在 Nginx 中实现集群级别的全局限流,本质是突破单机限制,让多个 Nginx 实例共享同一套限流状态。但需明确:Nginx 原生的 limit_req_zone 和 limit_conn_zone 仅支持本机内存共享,无法跨进程、更无法跨机器。因此,“集群级全局限流”必须借助外部组件协同完成,不能仅靠 Nginx 配置文件实现。
为什么原生 Nginx 不支持集群限流
Nginx 的限流模块(ngx_http_limit_req_module 和 ngx_http_limit_conn_module)依赖 本地共享内存区(shared memory zone) 存储计数器,例如:
limit_req_zone $binary_remote_addr zone=api:10m rate=100r/s;- 该
zone=api:10m仅存在于当前 Nginx worker 进程所在服务器的内存中 - 其他 Nginx 实例完全无法读写该区域,彼此状态隔离
可行的集群限流方案(需外部组件)
主流实践是将限流决策上移至一个中心化服务,Nginx 充当执行代理。以下是两种成熟路径:
方案一:Nginx + Redis(推荐,灵活可靠)
- 使用
nginx-plus(商业版)或开源模块lua-resty-limit-traffic+lua-resty-redis - 核心逻辑:每个请求到达时,Nginx 执行 Lua 脚本,向 Redis 发起原子操作(如
INCR+EXPIRE),判断是否超限 - 示例关键逻辑(Lua):
local limit = require "resty.limit.count" local lim, err = limit.new("redis://127.0.0.1:6379", 100, 1) -- 每秒100次 local key = ngx.var.binary_remote_addr local delay, remaining, err = lim:incoming(key, true) - 优势:支持精确速率、自定义 key(如用户ID、API 路径)、动态调整策略
方案二:前置统一网关层(如 Kong、APISIX、Traefik)
- 这些网关内置分布式限流插件,底层通常基于 Redis 或 etcd 实现状态同步
- Nginx 退为纯负载均衡器,所有流量先经网关做集群级限流,再转发至后端 Nginx 集群
- 例如 APISIX 的
limit-count插件可配置key为remote_addr,并指定 Redis 地址 - 优势:开箱即用、策略可视化、与鉴权/日志等能力天然集成
常见误区与替代思路
有人尝试用 Nginx 变量拼接“伪集群标识”,例如:
limit_req_zone $server_name:$binary_remote_addr zone=cluster:10m rate=50r/s;- 这仍是每台机器独立计数,只是 key 更细粒度,并非真正集群共享
- 若想近似“全局效果”,只能大幅降低单机阈值(如设为总目标的 1/N),但会牺牲突发容忍度且不精准
另一种轻量做法是:在 DNS 或 LVS 层做 IP 哈希调度,确保同一客户端始终落到同一台 Nginx —— 此时单机限流可等效为“会话级全局”,但失去高可用弹性,不推荐生产核心链路。











