least_conn不适用于静态文件场景,因其依赖长连接与真实活跃连接数,而静态文件响应快、连接极短,易导致Nginx误判负载;需隔离静态路径、禁用keepalive和HTTP/1.1复用,并确保健康检查路径轻量独立。

静态文件访问在 least_conn 模式下卡顿,本质不是算法本身的问题,而是该模式被错误用于不匹配的场景,或配套机制失真导致 Nginx “误判”了后端负载。静态文件本应毫秒级响应、连接极短,而 least_conn 的设计逻辑依赖**长连接 + 真实活跃连接数积累**——两者天然冲突。排查要从“为什么它会介入静态请求调度”开始。
确认 least_conn 是否真在调度静态请求
很多卡顿源于配置范围过大:把 least_conn 写在全局 upstream 中,却未对静态资源做路由隔离,导致本该直出的文件也被代理到后端集群。
- 检查
location块是否明确拦截静态路径(如location ~* \.(js|css|png|jpg|woff2)$),并直接root或alias到本地磁盘,不走proxy_pass - 若必须代理静态文件(如 CDN 回源),确保该
location使用独立的、不带least_conn的upstream,例如:upstream static_origin { server 10.0.1.20:80; } - 用
access_log加字段验证:log_format main '$remote_addr - $upstream_addr $request_time $upstream_response_time';,观察卡顿时$upstream_addr是否为空(说明未代理)或指向后端(说明被错误调度)
检查 keepalive 和连接复用是否反向干扰
静态请求生命周期短,若强制复用长连接,反而会造成连接池“虚高”和竞争延迟:
-
upstream中的keepalive 32对静态服务是冗余甚至有害的——空闲连接长期占位,让least_conn误以为某台后端“已满”,转而把新请求压向另一台,引发抖动 - 静态代理的
location中,应禁用 HTTP/1.1 复用:proxy_http_version 1.0;proxy_set_header Connection "close"; - 后端(如 Nginx 静态源站)也要关闭长连接:
keepalive_timeout 0;,避免维持无意义的 ESTABLISHED 连接
验证后端是否因连接堆积产生隐性排队
即使静态响应快,若后端连接处理模型有缺陷(如单线程、连接队列过小),least_conn 可能持续将请求导向同一台“看似连接少”的机器,实际触发内核连接队列溢出(netstat -s | grep "listen overflows")。
- 在后端机器执行:
ss -tn state established '( sport == :80 )' | wc -l,对比各节点数值是否异常偏高 - 检查后端
net.core.somaxconn和应用层最大连接数(如 Nginx 的worker_connections)是否足够,建议 ≥ 4096 - 临时停用
least_conn,改用ip_hash或轮询,观察卡顿是否消失——若消失,基本确认是调度策略与静态场景不兼容
排除健康检查误判导致的流量倾斜
主动健康检查(如 health_check interval=3)若探测路径也走静态资源,可能因瞬时并发高、文件缓存未命中,导致探测失败,反复摘除节点,剩余节点被迫承接全部流量。
- 健康检查路径必须独立且轻量,例如
/healthz,返回固定字符串,不读磁盘、不走业务逻辑 - 避免检查静态目录(如
/static/health.html),防止缓存失效或磁盘 I/O 波动引发误判 - 查看
nginx_status或日志中upstream的down状态变化频率,若频繁上下线,优先优化探测配置


















