nginx 不依赖多线程,而是通过异步非阻塞事件驱动模型处理请求;优化长耗时请求分配的关键是采用 least_conn 负载算法,结合 keepalive、超时设置与主动健康检查,实现后端连接数均衡与真实可用性感知。

直接用“线程分配”描述 Nginx 的行为其实不太准确——Nginx 本身不靠多线程处理请求,而是基于异步非阻塞的事件驱动模型(如 epoll/kqueue),每个 worker 进程单线程处理成千上万连接。所谓“优化长耗时请求的分配”,核心是让新请求更合理地落到当前压力最小的后端节点,同时避免连接堆积、超时中断和资源假空闲。关键不在 Nginx 自身开多少线程,而在负载策略、连接生命周期和后端感知三者的协同。
优先启用 least_conn 负载算法
轮询(round-robin)会无视后端真实负载,导致某台机器卡在 5 分钟的报表导出中,连接数持续飙升,而其他节点闲置;IP hash 更是彻底绑定客户端,完全失去动态调节能力。least_conn 则实时统计每个 upstream server 当前活跃连接数(含 keepalive 空闲连接),把新请求发给最“轻闲”的那台。
- 必须写在 upstream 块第一行:
least_conn; - 要求 Nginx ≥ 1.3.1(所有现代稳定版均满足)
- 不兼容
weight(开源版会静默忽略),但可用max_conns实现软容量控制:例如高性能节点设max_conns=2000,普通节点设max_conns=800,least_conn 只在各自上限内择优
配套 keepalive 与 timeout 设置
光写 least_conn 几乎没用——如果连接刚建就断、或空闲连接长期不回收,活跃数统计就失真,算法变成“盲选”。
- 在 upstream 块中启用连接复用:
keepalive 32;(建议值:32–100,过高会虚增活跃数,过低引发频繁重建) - 匹配业务最长耗时:如大文件上传需 2 小时,
proxy_read_timeout 7200;,否则 Nginx 提前断连,后端还在处理,连接反复新建又中断 - 客户端侧保持连接:
keepalive_timeout 75;(略大于后端服务的 connectionTimeout,避免 Nginx 先断而服务仍在忙) - 强制 HTTP/1.1 长连接:
proxy_http_version 1.1;并清空 connection 头:proxy_set_header Connection "";
加入主动健康检查防“假活”
least_conn 不识别后端是否已卡死或响应极慢。一台服务器 TCP 连接还通着,但应用线程池全满、请求排队 100+,least_conn 仍可能继续派发新请求。
- 推荐使用
nginx_upstream_check_module(需编译时启用)或 OpenResty 的check指令 - 示例:
check interval=3 rise=2 fall=3 timeout=1 type=http match=status_2xx; - 配合
max_fails=3 fail_timeout=30s,快速剔除实际不可用节点
验证是否真正生效
别只看日志请求数,要观察连接级分布:
- 开启
stub_status模块,访问/nginx_status查看各 upstream server 的Active connections是否随时间趋于均衡 - 压测时用
curl -I多次发起请求,比对各后端 access log 中remote_addr和连接建立时间戳的变化趋势 - 监控项重点看:
upstream_addr对应的活跃连接数、upstream_connect_time异常升高、upstream_response_time长尾











