nginx轮询算法通过默认轮询(顺序指针)和加权轮询(平滑加权机制)实现请求平滑分发,前者按server书写顺序循环分发,后者通过effectiveweight、currentweight和totalweight动态调度,确保流量在时间维度上均匀摊开。

Nginx 中轮询算法实现请求平滑分发,关键不在于“轮着来”这个表面动作,而在于它如何避免请求扎堆、防止某台服务器连续被选中——默认轮询靠顺序指针,加权轮询靠平滑加权机制,两者逻辑不同,但目标一致:让流量在时间维度上尽可能摊开。
默认轮询:靠固定顺序指针,天然均匀但需环境干净
它不看响应快慢、不记连接数、也不依赖任何状态,只按 upstream 中 server 的书写顺序循环推进指针:
- 第1个请求 → 发给列表第1台,指针移到第2位
- 第2个请求 → 发给列表第2台,指针移到第3位
- 第3个请求 → 发给列表第3台,指针回到第1位(循环)
这种机制轻量、确定、无开销。所谓“平滑”,体现在长期统计下各节点请求数基本一致;短期波动(比如连续3次都打到同一台)属正常现象,只要后端能力接近、没配置干扰,就不是算法问题,而是样本不足。
加权轮询:靠 currentWeight 动态演算,实现权重级平滑
当服务器性能不均时,Nginx 启用平滑加权轮询(Smooth WRR),核心是三个变量协同更新:
- effectiveWeight:初始等于配置 weight,但会随健康状况浮动(失败减1,成功加1)
- currentWeight:每次请求前,所有节点加上各自的 effectiveWeight;然后选出最大值者
- totalWeight:当前所有 effectiveWeight 总和,选中后该节点 currentWeight 减去 totalWeight
例如权重 {a:4, b:2, c:1},不会生成 [a,a,a,a,b,b,c] 这类集中序列,而是推导出类似 {a,b,a,c,a,b,a} 的分布——大权重节点被“拆开”,小权重节点也有机会穿插承接,真正缓解瞬时压力倾斜。
让平滑真正落地的实操要点
算法再好,配置一乱就失效。要确保平滑分发稳定生效,重点是清理干扰项并统一健康反馈:
- 删掉所有 weight=、ip_hash、hash $arg_xxx、least_conn 等指令——它们会覆盖或禁用轮询逻辑
- 每台 server 行保持裸写,如
server 10.0.1.10:8080;,不带等号、不带参数 - 为所有后端配置一致的探测参数,例如统一写
max_fails=2 fail_timeout=15s,避免某台因阈值宽松而长期滞留队列 - 用
$upstream_addr记录日志,真实看到每次请求落到哪台,比凭感觉判断更可靠
什么情况下轮询“不平滑”?其实是信号而非故障
如果发现请求明显偏向某台机器,大概率不是算法失灵,而是以下情况在发出提示:
- 某台 server 配了 weight=3 → 自动切为加权模式,不再是均等轮询
- 启用了 ip_hash → 请求被绑定 IP,轮询彻底失效
- 某台频繁超时触发临时摘除 → 轮询队列变短,剩余节点自然承接更多请求
- 后端处理耗时差异极大(如有的接口要3秒,有的30毫秒)→ 轮询不感知耗时,容易造成连接堆积,此时应考虑 least_conn
轮询本身不追求“绝对实时均衡”,它提供的是可预期、易验证、低开销的基础分发能力。把它的前提条件守住了,平滑就是自然结果。











