⚖️ Nginx 负载均衡算法

6 种算法原理 · 流程图解 · 交互演示 · 配置示例

📋

总览对比

Nginx upstream 支持的全部负载均衡策略

🚀 快速选择指南

  • 服务器性能一致 → 轮询 (round_robin)
  • 服务器性能不同 → 加权轮询 (weight)
  • 需要会话保持 → IP Hash
  • 请求处理时间差异大 → 最少连接 (least_conn)
  • 自定义路由规则 → 通用 Hash (hash)
  • 简单均匀分配 → 随机 (random)

📝 基础配置结构

upstream backend { server 10.0.0.1:8080; server 10.0.0.2:8080; server 10.0.0.3:8080; }
算法 指令 核心原理 会话保持 适用场景
轮询 (默认) 按顺序依次分配 服务器性能一致
加权轮询 weight=N 按权重比例分配 服务器性能不同
IP Hash ip_hash 客户端 IP 哈希映射 需要会话保持
最少连接 least_conn 分配给当前连接数最少的服务器 长连接/请求耗时差异大
随机 random 随机选择后端服务器 均匀分配,简单场景
通用 Hash hash $key 自定义 key 哈希映射 自定义路由规则
🔄

轮询 默认算法

Nginx 默认负载均衡策略,依次轮流分配请求

📐 原理说明

按照 upstream 中定义的服务器顺序,依次将每个新请求分配给下一台服务器。到达列表末尾后,从头开始循环。

这是最简单的负载均衡算法,不需要任何额外配置,Nginx 默认即使用此算法。

⚙️ 配置示例

upstream backend { server 10.0.0.1:8080; server 10.0.0.2:8080; server 10.0.0.3:8080; }
📐 轮询分配流程
客户端请求 #N
任意客户端发起请求
Nginx 接收
负载均衡器处理
取当前指针
i = N mod 总数
转发到 Server[i]
指针 i = (i+1) mod 总数
返回响应
等待下一个请求

▶ 交互演示(3 台服务器)

Server A
10.0.0.1
Server B
10.0.0.2
Server C
10.0.0.3

✅ 优点

  • 零配置,Nginx 默认即使用
  • 实现简单,无额外开销
  • 绝对均匀分配请求
  • 适合服务器性能一致的场景

❌ 缺点

  • 不考虑服务器实际负载
  • 不考虑服务器性能差异
  • 无法做会话保持
  • 服务器宕机需要配合 down 标记
⚖️

加权轮询 weight

根据服务器性能设置权重,按比例分配请求

📐 原理说明

Nginx 使用平滑加权轮询 (Smooth Weighted Round-Robin) 算法。

每轮选择前,每台服务器的 currentWeight += effectiveWeight,然后选出 currentWeight 最大的服务器,被选中的服务器 currentWeight -= totalWeight

这样保证:权重越高的服务器被选中越频繁,同时分配平滑均匀,不会出现连续集中分配的情况。

⚙️ 配置示例

upstream backend { server 10.0.0.1:8080 weight=5; # 高配 server 10.0.0.2:8080 weight=3; # 中配 server 10.0.0.3:8080 weight=1; # 低配 }
Server A (w=5)
Server B (w=3)
Server C (w=1)

权重比例 5 : 3 : 1 → 请求分配比例

📐 平滑加权轮询流程
新请求到达 Nginx
每台服务器 currentWeight += effectiveWeight
选出 currentWeight 最大的服务器
被选中的 currentWeight -= totalWeight
将请求转发给该服务器

▶ 交互演示(权重 5:3:1,共 9 轮)

A (w=5)
cw: 0
B (w=3)
cw: 0
C (w=1)
cw: 0

✅ 优点

  • 根据服务器性能合理分配
  • 平滑加权,分配均匀不集中
  • 高性能服务器承载更多请求
  • 灵活调整,运维方便

❌ 缺点

  • 权重需手动设定
  • 不考虑运行时实际负载变化
  • 无法会话保持
  • 服务器异构时需配合健康检查
🔑

IP Hash ip_hash

基于客户端 IP 的哈希映射,保证同一客户端始终访问同一服务器

📐 原理说明

对客户端 IPv4 地址的前三个八位组(或整个 IPv6 地址)进行哈希运算:

hash = hash(IP前3段) % server_count

同一 IP 的请求永远映射到同一台后端服务器,实现会话保持(Session Affinity)

⚙️ 配置示例

upstream backend { ip_hash; server 10.0.0.1:8080; server 10.0.0.2:8080; server 10.0.0.3:8080; }
📐 IP Hash 映射流程
客户端请求
携带源 IP 地址
提取 IP 前三段
192.168.1.100 → 192.168.1
Hash 运算
hash(192.168.1) % N
映射到 Server[i]
固定映射,不变

▶ 交互演示(3 台服务器,模拟多个 IP)

Server A
10.0.0.1
Server B
10.0.0.2
Server C
10.0.0.3

⚠️ 注意事项

✅ 优点

  • 天然会话保持,同一 IP 访问同一后端
  • 无需额外的会话共享方案
  • 配置简单,只需加一行 ip_hash

❌ 缺点

  • 无法保证请求均匀分配
  • 服务器宕机会导致会话迁移
  • CDN/代理环境下需额外配置
  • 不支持 weight 参数
📊

最少连接 least_conn

将请求分配给当前活跃连接数最少的服务器

📐 原理说明

Nginx 实时跟踪每台后端服务器的活跃连接数,新请求到来时,选择当前活跃连接数最少的服务器。

当配置了 weight 时,Nginx 使用加权公式:

选择 (active_conn × 256 / weight) 最小的服务器

这意味着权重高的服务器在同等连接数下更容易被选中。

⚙️ 配置示例

upstream backend { least_conn; server 10.0.0.1:8080 weight=3; server 10.0.0.2:8080 weight=2; server 10.0.0.3:8080 weight=1; }
📐 最少连接决策流程
新请求到达 Nginx
是否配置了 weight?
计算 conn × 256 / weight
选最小值
直接选 active_conn
最小的服务器
转发请求,更新连接计数

▶ 交互演示(3 台服务器)

Server A
连接: 0
Server B
连接: 0
Server C
连接: 0

✅ 优点

  • 动态感知服务器实际负载
  • 长连接场景表现优秀
  • 支持 weight 加权
  • 避免慢服务器堆积请求

❌ 缺点

  • 需要维护连接计数状态
  • 短连接场景优势不明显
  • 无法会话保持
  • 对突发流量可能不够平滑
🎲

随机 random

随机选择后端服务器,配合 two 参数可选中后随机再选一个

📐 原理说明

每个请求随机选择一台后端服务器。在请求数量足够大时,请求会近似均匀地分布到所有服务器上。

random [two] 模式:先随机选两台服务器,再从这两台中选出连接数更少的一台。结合了随机性和最少连接的优点。

⚙️ 配置示例

# 纯随机 upstream backend { random; server 10.0.0.1:8080; server 10.0.0.2:8080; server 10.0.0.3:8080; }
# 随机选两个,再选连接少的 upstream backend { random two; server 10.0.0.1:8080; server 10.0.0.2:8080; server 10.0.0.3:8080; }
📐 随机算法流程
新请求到达 Nginx
是否使用 random two?
否 — 纯随机
rand() % N
直接转发
是 — 随机两个
随机选 2 台服务器
选连接数少的转发

▶ 交互演示(纯随机,3 台服务器)

Server A
0 次
Server B
0 次
Server C
0 次

✅ 优点

  • 实现简单,无需维护状态
  • 大量请求下分配近似均匀
  • random two 兼顾负载感知
  • 无状态,适合分布式部署

❌ 缺点

  • 小请求量时分配不均匀
  • 纯随机模式无法会话保持
  • 不考虑服务器性能差异
  • 无法预测分配结果
🧩

通用 Hash hash

基于任意 key(变量)的哈希映射,灵活的会话保持方案

📐 原理说明

使用用户自定义的变量作为哈希 key,Nginx 计算哈希值后对服务器数量取模:

server_index = hash($key) % server_count

常用 key 包括:

  • $binary_remote_addr — 客户端 IP(比 ip_hash 更精确)
  • $request_uri — 请求 URI(缓存场景)
  • $arg_xxx — 查询参数(如用户ID、租户ID)
  • $cookie_xxx — Cookie 值

⚙️ 配置示例

# 基于 URI 哈希(缓存友好) upstream cache_backend { hash $request_uri consistent; server 10.0.0.1:8080; server 10.0.0.2:8080; server 10.0.0.3:8080; }
# 基于 Cookie 中的 user_id upstream user_backend { hash $cookie_user_id consistent; server 10.0.0.1:8080; server 10.0.0.2:8080; server 10.0.0.3:8080; }
📐 通用 Hash 流程(含 consistent 选项)
提取变量值
$request_uri / $cookie_xxx
Hash 运算
hash(key) → 数值
consistent?
一致性哈希 or 取模
映射到 Server[i]
转发请求

🔄 consistent 一致性哈希

添加 consistent 参数后使用一致性哈希算法(Ketama),其核心优势:

▶ 交互演示(基于 URI 哈希,3 台服务器)

Server A
10.0.0.1
Server B
10.0.0.2
Server C
10.0.0.3

✅ 优点

  • 灵活自定义路由 key
  • consistent 模式减少节点变更影响
  • 可基于任意业务维度做会话保持
  • 支持 weight 加权

❌ 缺点

  • key 选择不当可能导致分布不均
  • 纯 hash 模式节点变更影响大
  • 无法动态感知服务器负载
  • 需要理解一致性哈希原理