nginx的limit_req模块仅支持请求速率限制,不提供负载均衡或流量整形功能;差异化限流需结合geo/map指令按合作伙伴ip分组,并通过多zone或复合key实现精准控制,配合upstream与排队服务可达成软限流与流量整形。

nginx 的 limit_req 模块本身不提供负载均衡功能,也不能直接做“流量整形”(traffic shaping),它只支持请求速率限制(rate limiting)——即丢弃或延迟超出阈值的请求。所谓“针对不同合作伙伴 IP 的差异化限流”,是完全可行的;但若目标是“负载均衡 + 流量整形”,需明确分工:由 upstream 模块或第三方模块(如 nginx-plus 的 slow_start、queue)承担负载分发与平滑调度,而 limit_req 仅负责按 IP 分组施加请求频次控制。
按合作伙伴 IP 设置独立限流规则
核心思路是用 geo 或 map 指令将合作方 IP 映射为不同 key,再在 limit_req_zone 中基于该 key 定义多个限流维度:
- 使用
geo块预先标记合作方 IP 段,生成变量(如$partner_id),非合作方设为默认值(如0) - 用
map将$partner_id映射为限流等级标识(如"a"、"b"),便于复用 zone - 定义多个
limit_req_zone(推荐方式)或一个 zone + 复合 key(如$partner_id$uri),但注意共享内存大小需覆盖所有 key 的基数
避免全局锁竞争,提升高并发下限流精度
当合作方数量多、IP 散布广时,单 zone + 高基数 key 可能引发 slab 冲突和哈希碰撞,导致实际限流宽松。建议:
- 为头部合作方单独配置 zone(如
limit_req_zone $binary_remote_addr zone=partner_a:10m rate=100r/s) - 对中小合作方按等级聚合(如“银牌客户”共用
partner_silverzone,rate=30r/s) - 启用
limit_req dry_run(nginx 1.19.10+)做灰度验证,不真正限流但记录日志,确认 key 分布合理
与 upstream 协同实现“软限流”效果
单纯丢弃请求可能影响合作方体验。可结合 proxy_next_upstream 和自定义错误页,把被限流请求导向降级服务或排队中间件:
- 在
limit_req触发503时,用error_page 503 = @queue转交至内部排队 location - @queue 可 proxy_pass 到 Redis-backed 队列服务(如 Celery + Flask API),实现真正的流量整形(delay + buffer)
- 对关键合作方,用
limit_req burst=20 nodelay允许短时突发,再配合后端异步处理,比硬限流更友好
监控与动态调整限流策略
生产中需实时感知各 partner 的限流命中情况:
- 开启
limit_req_log_level warn,配合 log_format 记录$limit、$limit_rate、$limit_burst等变量 - 用
stub_status或nginx-module-vts查看各 zone 的当前请求数、拒绝数 - 通过 OpenResty + Lua 或外部配置中心(如 Consul KV),实现 partner 限流阈值的热更新,无需 reload nginx










