加权轮询的权重调得很细并不会线性带来更均衡的效果,多数情况下反而增加运维成本和排障复杂度。权重的本质只是一种粗糙的流量偏好,不是容量规划工具,把比例从 3:1 调到 97:33,收益远小于把一台故障实例从集群里摘掉的收益。
为什么”调得细”让人觉得有效
权重的直觉陷阱
很多人第一次调加权轮询时,是从 weight=1 和 weight=2 起步的,两台机器,一台新一台旧,旧的顶不住压力,调成 1:2 之后旧机器负载立刻降下来,这个效果太直观了,大脑很容易记住”调整权重能解决问题”。
但问题出在下一步,当集群变成 5 台机器,新旧差异没那么大时,有人会把权重调成 17:23:31:19:11,理由是”每台机器内存、CPU 型号都不同,精确一点总没错”,这个逻辑成立的前提是权重和真实容量严格线性相关,而线上流量根本不满足这个前提。
误差其实来自多个环节
请求从客户端到达后端服务器,中间经过 DNS 解析、连接池复用、网关转发、容器 CPU 限流、GC 停顿、数据库连接等待,每一个环节都会引入抖动,两台配置完全相同的机器,同一批流量,实际吞吐也可能差出 3% 到 5%,在这个噪声背景下,把权重从 60:40 细调到 63:37,调度结果并不会按你预想的比例走。
同时请记住加权轮询是一个无状态调度,它不关心上一次转发是否成功,也不关心某台机器当前是否已经积压了大量慢请求,按轮子顺序转圈发送,不对后端做任何探活,据 Nginx 官方文档说明,加权轮询只是按权重计算挑选次数,服务器是否真的能处理,交给健康检查和被动超时兜底,因此细调权重去对抗瞬时波动,是用错了工具。
细粒度权重的三个隐性代价
配置维护成本暴涨
权重一旦调细,扩容和缩容就变成一场算术考试。
- 原来 3 台机器,权重 3:2:1,扩容 2 台,需要让新机器参与进来并保持总比例不变。
- 测试环境、预发环境、生产环境三套配置容易出现漂移,环境 A 用 5:4:1,环境 B 用 8:7:1,排障时无法互相参照。
- 每次发布脚本里改完权重,还要人工校验是否互质、是否算错公约数。
这些成本非常真实,很多团队最后演进成从配置文件里直接删掉权重,或者干脆全部写 weight=1,让负载均衡器平均转发。
统计噪声压倒信号
短时间窗口的流量分布是极其不均匀的,一个用户长连接可能持续占用某台后端 30 秒,期间新请求不断堆积到同一台机器,此时你观察到的流量比例和权重比例完全对不上,业内专家指出,大多数线上服务的流量波动在分钟级,权重精度在几个百分点内的变化对整体吞吐影响很小。
一个简单的验证方法:把权重差控制在 5% 以内,然后去看后端 CPU 曲线,你会发现曲线几乎重合,差异甚至没有重启一次容器带来的波动大,你以为权重生效了,其实是随机波动。
瓶颈转移与假定位
权重调得细,人就会下意识相信”既然比例没问题,一定是后端有问题”,于是反复排查后端健康状态、日志、慢查询,最后才发现根因在别处。
举一个很常见的例子:你根据 CPU 核数把权重设为 2:1,压测时发现第二台机器负载冲高,误以为是权重倒挂,实际上瓶颈出现在两台机器共享同一个数据库连接池,连接池被打满,后端再快也快不起来,此时无论把权重调成 3:1 还是 5:1,效果都是零,反而让第一台机器多承担了本不该承担的流量。
什么场景下细粒度权重才真正值得
细调权重不是一无是处,但适用场景很有限。
- 集群内存在代际差异极大的硬件,比如同一批流量中混有上一代 CPU 和最新一代 CPU,吞吐可能相差 40% 以上。
- 后端服务运行在不同规格的容器里,有的实例分配 4 核,有的分配 0.5 核。
- 请求处理时长严重不均,例如某台机器上存在跨可用区访问,网络 RTT 高出其他机器一大截。
在这些场景下,权重差远远大于噪声,4:1 甚至 10:1,这时细调才具备现实意义。
用”粗粒度 + 动态调度”替代超细权重
大多数业务不需要走到细调那一步,行业共识认为,把服务器按性能分成大、中、小三档,分别给 3、2、1 的权重就够了,剩下的偏差交给动态调度算法去纠正。
Nginx 自带的 least_conn 算法(最少连接),相比静态加权轮询,它会把新请求转发给当前连接数最少的那台后端,实测下来,在请求处理时间不均匀的场景下,
least_conn 的效果好过任何一组静态权重,配置示例:
upstream backend {
least_conn;
server 10.0.0.1;
server 10.0.0.2;
server 10.0.0.3;
}
另一个替代方案是给负载均衡层增加被动健康检查,连续失败几次自动摘除节点,这个机制比权重的精度更能保护整体可用性。
一个可复用的权重配置流程
如果确定需要手动配置权重,推荐按照下面这个方法,而不是拍脑袋定数字。
操作步骤
- 给所有后端实例打标,记录 CPU 核数、内存、磁盘类型、网络带宽。
- 按 CPU 核数比算出初始权重,4 核对 2 核,初始权重 2:1。
- 用压测工具(如
wrk、ab或云厂商自带的压测服务)施压,记录每台实例的吞吐和错误率。 - 把吞吐差异映射回权重,差异超过 30% 才调整,低于 30% 的差异直接忽略。
- 凡是计算后权重差小于 2 的实例,全部归一化成同一档。
粗粒度与细粒度的实际对比
| 项目 | 粗粒度权重(3:2:1) | 超细权重(17:13:9:11:7) |
|---|---|---|
| 日常配置耗时 | 一分钟内搞定 | 需要算公约数和验算 |
| 排障定位速度 | 看整体即可 | 需要逐台对比 |
| 应对突发流量 | 依赖动态算法兜底 | 权重跑偏时反而放大问题 |
| 配合健康检查 | 效果好 | 差别不明显 |
| 典型适用规模 | 5 台以上常规集群 | 服务器性能差超过 3 倍 |
这套流程适合大多数 Web 服务、微服务网关以及自建 Nginx/OpenResty 集群,如果使用的是云负载均衡产品(比如简米云 SLB、酷番云 CLB),控制台里通常只提供整数权重且对总权重有隐含限制,更不需要把比例设计得太精细。
Nginx 实际配置示例
upstream backend {
server 10.0.0.1 weight=3;
server 10.0.0.2 weight=2;
server 10.0.0.3 weight=1;
keepalive 32;
}
这段配置中 10.0.0.1 和 10.0.0.2 分别是主力和备主力,10.0.0.3 接收少量流量用来灰度新版本,灰度验证通过后,把 10.0.0.3 的 weight 改成 2,平滑接入全量流量,这是最常见的升级路径,不需要每台机器都精确到个位数。
权重的精度不是越高越好,你的目标是让整体吞吐最大、错误率最低,而不是让流量比例和权重比例严格一致。粗粒度权重加动态调度,永远是性价比最高的组合。 把省下来的精力放到健康检查、超时重试、容量监控上,效果比抠小数点的权重好得多。
关于加权轮询权重设置的常见问题
负载均衡轮询算法怎么调优?
先看后端实例之间的性能差异,再决定用哪种算法,差异小于 2 倍,直接使用普通轮询或者最小连接数,配置 least_conn 后按请求数量自动调度,差异大于 3 倍,才需要手动设置 weight,调优时从 3:2:1 这样的粗粒度开始,压测后观察错误率曲线,不建议直接跳到 17:13:9 这类复杂比例。
加权轮询和最少连接数哪个好?
取决于请求处理时间,如果所有后端实例处理单个请求的速度基本稳定,加权轮询的命中率误差很小,足以胜任,如果请求处理时间长短混杂,例如存在大文件下载和普通 API 混跑的情况,最少连接数能把新请求分给最空闲的实例,明显优于静态权重,一个常见的组合是:保留权重用来表达机器容量差异,同时开启最少连接数作为调度基准。
Nginx 权重配置后流量不均衡怎么办?
首先检查 upstream 块里是否写入了相同的权重但实际生效的是默认 1:1,刷新 Nginx 配置后确认 nginx -s reload 执行成功,然后查看后端实例的连接数和 CPU,排除健康检查关闭导致请求打到故障实例的情况,再确认是否有本地 DNS 缓存或者客户端长连接导致连接被复用在固定后端,此时负载均衡层面的比例没有问题,是客户端侧连接复用造成的假性不均衡,最后抓取一段 10 分钟粒度流量,观察比例偏差是否在 10% 以内,以上各步骤仍未解决,再考虑调整权重,但每次只改一个单位并观察 24 小时。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/633111.html





