nginx分布式限流需借助外部共享存储实现同步,因原生limit_req/limit_conn仅单机有效;推荐redis+lua原子计数,或openresty shared_dict近似同步,亦可将限流上收至api网关统一管控。

Nginx 本身是无状态的反向代理,不自带分布式限流同步能力。它原生的 limit_req 和 limit_conn 模块只在单机内存中计数,多节点部署时各节点独立统计,会导致限流失效——比如你设了“每秒最多5次请求”,但4台Nginx各自放行5次,实际就变成了20次。
用共享存储做统一计数器
核心思路:把计数逻辑从 Nginx 本地内存移到外部共享存储,让所有节点读写同一份数据。
-
Redis + Lua 是最常用组合:利用 Redis 的原子操作(如
INCR、EXPIRE)配合 Lua 脚本实现毫秒级精确限流,Nginx 通过lua-resty-redis或ngx_http_lua_module调用 - 示例逻辑:按用户 ID 或 API 路径拼 key,比如
rate:uid_123:/api/order,每次请求执行INCR并设置过期时间(如 60 秒),超阈值则返回 429 - 注意 Redis 连接池配置和超时控制,避免因 Redis 延迟拖慢整个请求链路
用 OpenResty 共享字典(shared_dict)做近似同步
适用于对一致性要求不高、但追求极致性能的场景。
-
shared_dict是 OpenResty 提供的跨 Worker 进程共享内存,但不跨节点;要“伪同步”,需配合一致性哈希或定时广播机制 - 常见做法:用 Nginx 变量(如
$binary_remote_addr)做 key,将计数缓存在 shared_dict 中,并设置较短的 TTL(如 10s),再由后台任务定期将热点 key 同步到 Redis - 优势是延迟低、无网络开销;缺点是节点间有短暂窗口不一致,适合防刷、压测防护等容忍误差的场景
边缘网关层统一限流,Nginx 降级为执行单元
把限流决策上收,让 Nginx 只负责转发和简单校验。
- 在 API 网关(如 Kong、APISIX 或自研网关)集中管理限流规则,基于用户身份、令牌、标签等维度动态下发策略
- Nginx 配置为轻量级代理,仅做
limit_req做兜底(比如单 IP 连接数限制),或通过auth_request模块调用网关鉴权接口实时判断是否放行 - 这种方式解耦清晰,规则可热更新、可灰度、可审计,适合中大型微服务架构
避免常见陷阱
分布式限流不是加个 Redis 就完事,几个关键细节决定成败:
- Key 设计必须包含业务上下文,不能只用 IP:否则登录用户换设备就失效,未登录用户又会误伤
- 时间窗口要对齐:多节点若用本地时间计算滑动窗口,可能因时钟漂移导致统计偏差,建议用 Redis 的
TIME或统一 NTP 服务校准 - 失败降级策略必须明确:Redis 不可用时,是拒绝全部请求(保守)、放行全部(激进),还是切换到本地漏桶(折中)?需根据业务 SLA 决定
- 不要忽略连接级限流:
limit_conn在分布式下虽难同步,但可在接入层(如四层 LB)做 IP 连接数硬限制,作为第一道防线











