精准流量管控需按活跃IP数×64字节建模内存,结合map降维、分层zone设计,并通过日志、状态页、共享内存使用率三指标验证——否则限流失效或资源浪费。

精准的流量管控不是靠堆内存或调高 burst,而是从共享内存容量与真实活跃基数之间建立可验证的数学关系。千万级并发下,limit_req_zone 的内存必须按每个 IP 约 64 字节精确建模,并结合业务维度降维,否则要么限流失效,要么资源严重浪费。
按活跃 IP 数算准内存底数
每个被记录的客户端(使用 $binary_remote_addr)在 64 位 Nginx 中实际占用约 64 字节:含 IPv4 地址(4 字节)、计数器(8 字节)、时间戳、哈希桶指针及锁结构等管理开销。实测 1MB 共享内存 ≈ 存储 1.6 万个活跃 IP。
- 若监控/日志统计出峰值并发活跃 IP 为 500 万 → 理论最小内存 = 5,000,000 × 64 ÷ 1,048,576 ≈ 305 MB
- 生产环境必须预留 20%~30% 冗余(防哈希冲突、突发增长、状态抖动),建议配置
zone=ip_limit:400m - 切忌写
10m或100m—— 这点空间连 1% 的活跃 IP 都存不下,会导致旧状态被频繁挤出,限速形同虚设
用 map 降维 key,避免全量记 IP
直接以 IP 为 key 是线性膨胀模型,千万级下内存不可控。应通过 map 提取语义化、聚合型标识,把高基数 IP 映射到低基数逻辑单元:
- 地域粗粒度:用
$geoip2_country_code作为 key,单个 key 覆盖数万 IP,zone=country_limit:10m rate=1000r/s - 用户身份优先:后端透传
$http_x_user_id,真实用户数远少于 IP 总量,zone=user_limit:20m rate=5r/s - 行为路径分类:对导出接口统一打标
map $request_uri $is_export { ~^/api/.*/export 1; default 0; },再用zone=export_limit:5m rate=1r/m - 拒绝使用
$request_uri或长 cookie 值做 key —— 熵值过高,极易撑爆内存且无业务意义
分层 zone 设计,让内存各司其职
不把所有压力压在一个大 zone 上,而是按风险等级、调用频次、生命周期拆分多个小 zone,总内存可控,但覆盖能力更强:
-
zone=login_limit:2m rate=3r/m:登录页,key 为 IP,速率极严,长期存活 IP 少,内存轻量 -
zone=api_burst:8m rate=200r/s:高频 API,key 为$server_name:$binary_remote_addr,隔离不同服务的 IP 状态 -
zone=static_limit:50m rate=100r/s:静态资源,key 可放宽为 IP 前缀(如$remote_addr ~^(?P<ip2>\d+\.\d+)\.),大幅压缩槽位 - 每个 zone 独立配置、独立监控、独立扩容,避免单点瓶颈和状态污染
上线后必须验证内存是否真够用
配置生效 ≠ 内存够用。需通过三项指标交叉验证:
- 查
error.log是否高频出现limiting requests, excess:日志,且同一 IP 状态反复消失 → 很可能是内存不足导致状态被强制淘汰 - 用
curl -s 'http://127.0.0.1/nginx_status' | grep limit(需开启 stub_status)观察命中/拒绝计数突增,结合请求分布判断是否漏判 - 采集
shm_zone_ip_limit_used_size指标(通过 vts 或 OpenResty Prometheus 模块),当使用率持续 >85%,立即扩容对应 zone

















