HTTP/2下limit_conn统计偏差源于其按TCP连接而非请求限流:一个TCP连接可承载大量并发流,导致limit_conn addr 10形同虚设;应改用limit_req控制请求速率,并确保real_ip配置正确以精准识别客户端。

排查 limit_conn 在 HTTP/2 多路复用下的统计偏差,关键不是怀疑模块本身失效,而是理解它统计的“连接”与 HTTP/2 的语义不一致:Nginx 的 limit_conn 统计的是 TCP 连接数,而一个 HTTP/2 连接可承载成百上千个并发流(streams)。同一个客户端只建一个 TCP 连接,却发起大量请求,limit_conn addr 10 就会形同虚设——它只限制了 10 个 TCP 连接,而非 10 个并发请求。
确认是否真被多路复用影响
检查 access 日志中是否出现大量请求来自同一 IP + 同一 $remote_addr,但响应极快、无连接建立延迟迹象。更直接的方法是开启调试日志:
- 在
http块添加:log_format debug '$remote_addr - $connection $connection_requests | "$request" $status'; - 对目标 server 或 location 启用该格式,并发起多个并发请求(如用
h2load -n 100 -c 10) - 观察日志:若
$connection值长期不变(比如始终是 12345),而$connection_requests持续飙升(如从 1 到 87),说明复用已发生,limit_conn对这个连接只会计 1 次
区分限流目标:连接 vs 请求
HTTP/2 场景下,单纯靠 limit_conn 控制“连接数”已无法约束真实并发压力。应按需切换策略:
- 若目标是防止单个客户端耗尽服务资源(如后端线程池),优先使用
limit_req,基于$binary_remote_addr限制每秒请求数或突发请求数 - 若仍需控制连接层负载(如避免过多 TLS 握手或文件描述符耗尽),可配合
listen ... http2 backlog=xx和系统级net.core.somaxconn调优,但不要依赖limit_conn做业务级限流 - 不建议用
$http_host或$request_uri做limit_connkey,它们与连接数无直接关系,且易被绕过
验证 real_ip 与连接统计的一致性
多层代理 + HTTP/2 容易加剧 IP 识别混乱,导致 $binary_remote_addr 不是真实客户端,进而让 limit_conn 限错对象:
- 确保
real_ip_module已启用,且set_real_ip_from精确填写 CDN/WAF 回源网段 - 检查
real_ip_header是否匹配上游实际头字段(例如 Cloudflare 是CF-Connecting-IP,不是X-Forwarded-For) - 在调试日志中比对
$remote_addr和$http_x_forwarded_for:若前者是内网地址而后者含公网 IP,说明 real_ip 未生效,limit_conn实际在对代理 IP 限流
规避误判的配置建议
避免把 limit_conn 当作 HTTP/2 下的“并发请求数”控制器:
- 禁用
limit_conn在location /api/这类高频接口路径上,改用limit_req zone=api burst=50 nodelay - 如必须保留连接限制,仅用于
/download/等大文件传输路径,并搭配limit_rate防止单连接占满带宽 - 监控指标应聚焦
nginx_http_connections_active(来自 stub_status)和connection_requests总量,而非仅看被拒绝连接数


















