在nginx负载均衡层启用limit_req是应对代理流量突发冲击最有效方式,需按代理特征设计key、分级配置burst/nodelay、闭环监控并补足连接层防护。

直接在 Nginx 负载均衡层启用 limit_req,是应对代理流量突发冲击最有效的方式。它不依赖后端、无额外延迟,把限流逻辑压到流量入口,让恶意或误配的代理请求在触达应用前就被识别和控制。
按代理特征设计限流 key,避免被绕过
普通 IP 限流对使用代理池、IP 轮换的流量效果有限。需结合可透传的代理标识做更精准识别:
- 若代理层透传真实用户标识(如
X-Real-User-ID或X-Forwarded-For中可信段),用$http_x_real_user_id或提取后的可信 IP 作为 key,比单纯用$binary_remote_addr更可靠 - 对已知代理网段(如某 CDN 或爬虫服务商 IP 段),可用
geo指令标记,再配合map构造特殊 key,例如:map $geo_proxy $limit_key { default $binary_remote_addr; 1 "$binary_remote_addr:proxy"; },然后基于$limit_key定义 zone - 组合维度更稳妥:用
"$limit_key$request_uri"区分不同接口路径,防止一个代理刷多个接口耗尽单个 key 配额
burst 与 nodelay 必须按代理行为分级配置
代理流量常表现为高频率、低延迟、无感知重试——这决定了 burst 不能设大,nodelay 不能乱开:
- 对疑似扫描类代理(如高频访问
/robots.txt、/api/health):设burst=0或burst=1+nodelay,超速即拒,不给排队机会 - 对业务型代理(如前端统一网关、第三方调用方):允许短时缓冲,
burst = rate × 1~1.5 秒,例如rate=20r/s → burst=30,但必须关闭nodelay,让超量请求排队而非瞬间压向后端 - 禁止在全局
location /上统一加nodelay,否则健康检查、静态资源等低风险路径也会触发激进拒绝,反而干扰运维判断
必须闭环:日志、状态码、内存监控缺一不可
没有可观测性的限流等于没开。代理流量往往隐蔽,靠默认日志很难定位问题源头:
- 在
log_format中强制加入$limit(触发的 zone 名)和$limit_key(实际统计值),例如:'$remote_addr $http_x_forwarded_for - [$time_local] "$request" $status $limit "$limit_key"' - 用
limit_req_status 429将拒绝响应码从默认503改为标准429 Too Many Requests,方便代理方识别并退避,也利于前端埋点统计 - 定期检查共享内存 zone 使用率:
nginx -T 2>/dev/null | grep "zone="查 size,确认是否足够——1MB ≈ 1.6 万个 key;若代理 IP 日活 20 万,zone 至少配 12MB,否则旧记录被挤掉,限流失效
补足连接层防护,防慢速代理耗尽资源
仅控请求速率不够。代理可能建大量长连接却不发数据(Slowloris 类攻击),或复用连接高频发请求:
- 叠加
limit_conn:用limit_conn_zone $binary_remote_addr zone=conn_perip:10m,再在关键 location 加limit_conn conn_perip 50,限制单 IP 并发连接数 - 调小
keepalive_timeout(如设为 15s),缩短空闲连接生命周期,降低连接堆积风险 - 对明确为代理的请求头(如
User-Agent: *bot*或含X-Forwarded-For多级 IP),可结合if+return 403做前置拦截(注意:仅用于简单过滤,不替代限流)











