nginx/HTTP 上游负载均衡

用平滑加权轮询分散上游请求

nginx 按有效权重累加候选节点的得分,选中最高分节点后减去总权重,让请求按权重交错分配。

release-1.26.3通信与流量核验 2026-10-09
相关概念

工程问题#

不同上游节点的承载能力不同;直接连续派发一整批权重份额会制造短时集中,请求重试、连接上限和故障节点还会改变候选集合。

实际实现#

ngx_http_upstream_get_peer 遍历 peer 链表,先排除本次已尝试、被停用、处于失败窗口或已达连接上限的节点。合格节点的 current_weight 加 effective_weight,选最高分节点,再从其得分减去本轮有效权重之和。

处理流程#

  1. 筛掉当前不可选或本次已尝试的节点
  2. 每个候选累加有效权重,记录得分最高者与本轮总权重
  3. 选中节点扣除总权重,并在本次请求的 tried 位图中标记

源码片段#

固定版本 · 原文摘录
src/http/ngx_http_upstream_round_robin.crelease-1.26.3 · L565–L575
查看原文件
565        peer->current_weight += peer->effective_weight;566        total += peer->effective_weight;567568        if (peer->effective_weight < peer->weight) {569            peer->effective_weight++;570        }571572        if (best == NULL || peer->current_weight > best->current_weight) {573            best = peer;574            p = i;575        }
ngx_http_upstream_get_peer · 累计并选取

对已通过前置可用性检查的候选累加 effective_weight,并记下 current_weight 最大的节点。低于配置值的有效权重在此逐步恢复。

src/http/ngx_http_upstream_round_robin.crelease-1.26.3 · L578–L595
查看原文件
578    if (best == NULL) {579        return NULL;580    }581582    rrp->current = best;583584    n = p / (8 * sizeof(uintptr_t));585    m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));586587    rrp->tried[n] |= m;588589    best->current_weight -= total;590591    if (now - best->checked > best->fail_timeout) {592        best->checked = now;593    }594595    return best;
ngx_http_upstream_get_peer · 扣除本轮总权重

无候选则返回 NULL;成功时标记本次已尝试节点,再从胜者 current_weight 中减去本轮 total,影响下一轮排序。

两个连续源码片段分别展示权重累计和胜者扣分;候选过滤及失败降权请通过来源链接查看完整函数。

收益与取舍#

工程分析

带来的收益

  • 以累计得分将不同权重的请求份额交错分配
  • 选择过程同时纳入失败状态、重试范围和连接上限

付出的代价

  • 工程分析:该路径每轮扫描候选链表,选择成本为 O(n)
  • 权重表达配置份额,不直接反映请求耗时;完成时间与瞬时负载仍可能不同
  • 失败回调会降低 effective_weight;它与配置 weight 并非始终相等

可比较的选择

最少连接按当前连接占用选择节点,更侧重在途负载;仍不能直接估计每个请求的计算量。

一致性哈希侧重相同键的路由稳定性,而非按每次请求重新分配份额。

版本与适用范围#

nginx release-1.26.3 的 HTTP upstream round-robin 路径。比例直觉建立在权重与可用候选相对稳定的条件下;单节点、backup 切换与重试还有外围处理。

参考来源#

源码、官方文档与原始论文
01
nginx · ngx_http_upstream_get_peer

src/http/ngx_http_upstream_round_robin.c · ngx_http_upstream_get_peer

源码release-1.26.3
02
nginx · ngx_http_upstream_free_round_robin_peer

src/http/ngx_http_upstream_round_robin.c · ngx_http_upstream_free_round_robin_peer

源码release-1.26.3

相关实现与比较#

4 个相关案例
8 个匹配案例