Skip to content
Go back

Nginx负载均衡——5种算法与生产实践

Nginx 负载均衡:5 种算法 + 生产配置

一句话结论(30s)

Nginx 五种负载均衡算法各有适用场景——因为轮询适合后端均等、加权轮询用平滑算法避免打桩、IP 哈希保持会话、URL 一致性哈希最小化缓存失效、最短时间适合性能差异大,所以选型取决于后端是否同质、是否有状态、是否有本地缓存。

核心原理(2min)

底层深入(5-10min)

5 种算法

1. 轮询(Round Robin,默认)

upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

请求依次均匀分发。适合所有后端性能相同的场景。

2. 加权轮询(Weighted Round Robin)

upstream backend {
    server 192.168.1.10:8080 weight=3;  # 新机器,性能好,多分
    server 192.168.1.11:8080 weight=1;  # 老机器,少分
}

Nginx 加权轮询使用平滑算法——不是简单按权重轮流(3→1→3→1…),而是动态计算 currentWeight,让高权重节点分散出现,避免”打桩”效应(连续 3 次打到同台机器)。

想一想:为什么加权轮询要用平滑算法? 因为如果按权重机械地”3 次 A → 1 次 B”循环,高权重节点会连续被打桩 3 次,瞬时负载不均;平滑算法动态维护每个节点的 currentWeight,让高权重节点”分散地、穿插地”多出现几次,最终比例仍符合权重,但任意时刻的负载都更均匀——这是”长期公平”和”瞬时均衡”的兼得。

3. IP 哈希(IP Hash)

upstream backend {
    ip_hash;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

同一客户端 IP 的请求始终路由到同一后端。适合有状态服务(Session 非共享),但后端扩缩容时哈希重新分布、部分用户 Session 丢失。

想一想:为什么 IP 哈希在扩缩容时会 Session 失效? 因为路由规则是 hash(客户端 IP) % 节点数,节点数一变,取模结果全变了,大量用户的请求会被路由到另一台机器,原来那台上的 Session 就”找不到了”。所以 IP 哈希适合节点数稳定的场景,频繁扩缩容要用一致性哈希或共享 Session。

4. URL 哈希(Hash)

upstream backend {
    hash $request_uri consistent;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

同一 URL 走同一后端——适合后端有本地缓存热点 URL 的场景。consistent 关键字启用一致性哈希,扩缩容时只影响相邻段的数据,最小化缓存失效。

想一想:为什么一致性哈希扩缩容只影响相邻段? 因为它把哈希值映射到一个环上,每个节点占据环上的一段;增删一个节点,只把”它相邻那一段”的数据重新分配,其他大部分数据仍在原节点。相比取模法”一改全乱”,一致性哈希把缓存失效的范围从”全部”缩小到”一小段”,这正是 consistent 关键字的价值。

5. 最短响应时间(Least Time)

upstream backend {
    least_time header;
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
}

Nginx Plus(商业版)特性。选择当前响应时间最短的后端。适合后端性能差异大或负载不均匀的场景。

健康检查 + 故障转移

upstream backend {
    server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;

location /api/ {
    proxy_pass http://backend;
    proxy_next_upstream error timeout http_500 http_502 http_503;
    proxy_next_upstream_tries 2;   # 最多重试 2 个后端
    proxy_next_upstream_timeout 5s; # 重试总超时 5 秒
}

max_fails=3 fail_timeout=30s:30 秒内连续 3 次失败 → 标记为 down → 30 秒后重试。

proxy_next_upstream:当返回 error/timeout/5xx 时自动重试下一个后端。重试次数和超时都要设置上限——无限重试会放大故障。

想一想:为什么故障重试要设上限? 因为如果第一个后端挂了、重试又打到另一个也慢的后端,再重试、再重试……一个请求的耗时会被无限放大,反而把本已脆弱的系统压得更狠。设置 proxy_next_upstream_tries 和超时,等于给”自动重试”加上熔断,防止故障被重试放大成全链路雪崩。

总结

算法适用场景限制
轮询后端性能均等不考虑负载差异
加权轮询后端性能不均需要手动配权重
IP 哈希有状态服务扩缩容 Session 失效
URL 哈希本地缓存场景热点 URL 负载不均
最短时间性能差异大商业版特性

章末提问

Q1:加权轮询为什么要用平滑算法,不平滑会怎样? 结论先行:不平滑会出现”打桩”效应——高权重节点被连续命中多次,瞬时负载不均。 因为按权重机械循环(如 3:1 就是 A、A、A、B),高权重机器会连续承接多次请求,某一瞬间被打满。平滑算法动态维护 currentWeight,让高权重节点穿插出现,长期比例仍符合权重,但任意时刻的负载都更均匀。

Q2:IP 哈希有什么缺点?什么场景适合用? 结论先行:缺点是扩缩容会导致哈希重分布、大量 Session 失效;适合”有状态且节点数稳定”的场景。 因为路由是 hash(客户端 IP) % 节点数,节点数一变取模结果全变,用户被路由到新机器,旧 Session 丢失。所以它适合需要”同一用户始终打到同一台、且后端很少增减”的场景;频繁扩缩容应改用一致性哈希或共享 Session。

Q3:一致性哈希为什么能最小化缓存失效? 结论先行:因为它把节点映射到哈希环上,增删节点只影响相邻一段,而不是像取模法那样全部重排。 因为每个节点只负责环上的一段区间,新增/下线一个节点,只需把相邻区间的数据重新分配,其他大部分数据仍在原节点、缓存继续命中。相比 hash % N 的”一改全乱”,一致性哈希把失效范围从”全部”缩到”一小段”。


Share this post on:

Previous Post
OSI七层模型与TCP/IP四层模型
Next Post
HTTP长连接 vs WebSocket——从半双工到全双工的演进