---
title: 负载均衡与路由
type: concept
domain: microservice
tags: [microservice, load-balancing, round-robin, consistent-hash, nginx, ribbon, service-mesh]
status: learning
created: 2026-09-27
last_reviewed: 2026-09-27
method: feynman
related_questions:
  - "什么是负载均衡，有哪些常见算法？"
related_knowledge:
  - ./nacos-core.md
  - ./microservice-communication.md
anki_cards: 6
interview_rounds:
  - "2026-09-27-round-1-Q7"
---

# 负载均衡与路由

> 负载均衡是把流量分给多台机器，让每台负载接近，提高吞吐、隐藏单点故障。核心是**位置分层（网络/应用/客户端）** + **算法选型**。

## TL;DR（30 秒扫完）

- **位置 3 层**：网络层（LVS/F5）+ 应用层（Nginx/HAProxy）+ 客户端（Ribbon/LoadBalancer/Dubbo Consumer）
- **7 大算法**：轮询 / 加权轮询 / 随机 / 加权随机 / 一致性哈希 / 最短响应时间 / 最少活跃连接
- **取模死穴**：节点扩缩容导致几乎所有 key 重分，缓存全失效——不适合缓存场景
- **一致性哈希**：哈希环 + 虚拟节点，扩缩容只影响 N/K 请求，避免缓存击穿

## 关键结论

- **结论 A**：客户端 LB 和 服务端 LB 是不同位置，各有优劣——不是替代关系
- **结论 B**：轮询（Round Robin）和加权轮询是默认算法，简单且均衡
- **结论 C**：一致性哈希 + 虚拟节点是缓存分片场景的关键，取模不适合扩缩容频繁的系统
- **结论 D**：一致性哈希本质是"哈希环 + 顺时针取第一个节点 + 虚拟节点解决数据倾斜"

## 完整讲解（费曼四步）

### STEP 1 · 概念

负载均衡（Load Balancing）是把网络流量分发到多个后端实例的机制，目的是提高吞吐、隐藏单点故障、支持水平扩展。

### STEP 2 · 大白话

**类比餐厅排队**：多开几台窗口（后端实例），叫号员（负载均衡器）按策略分客人（请求）——保证每个窗口都不空转、客人平均等待时间最短。

### STEP 3 · 底层

**3 层位置**：

| 层级 | 代表 | 特点 |
|------|------|------|
| 网络层（L4） | LVS、F5 | 快但只看 IP+端口，不支持 HTTP 特性 |
| 应用层（L7） | Nginx、HAProxy | 支持 HTTP/gRPC，可看请求头/路径 |
| 客户端 | Ribbon、Spring Cloud LoadBalancer、Dubbo Consumer | 无第三方、性能高，但每个客户端要实现 |

**7 大经典算法**：

| 算法 | 特点 | 适用场景 |
|------|------|---------|
| 轮询（Round Robin） | 最简单、默认算法 | 同构机器 |
| 加权轮询 | 按权重分配 | 异构机器（8C16G vs 4C8G） |
| 随机 / 加权随机 | 统计上均衡，短期有波动 | 简单场景 |
| 一致性哈希 | 扩缩容只影响 N/K 请求 | 缓存分片、会话保持 |
| 最短响应时间 | 按历史响应时间选 | 后端性能差异大 |
| 最少活跃连接 | 按并发数选 | 长连接后端（MQ Consumer） |

**取模的死穴**：假设有 N 台机器，取模 N 分配；扩容到 N+1 后，几乎所有 key 的取模结果都变了，导致**所有缓存失效、请求雪崩到后端**。

**一致性哈希原理**：
1. 哈希环（0~2^32）
2. 所有节点映射到环上（顺时针）
3. 请求也映射到环上，顺时针取第一个节点
4. 扩容时新节点抢占原有虚拟节点的数据范围
5. **虚拟节点**（一般 150 个/节点）避免数据倾斜：每真实节点在环上生成 100-200 个虚拟节点，让数据分布更均匀

**典型场景选型**：
- 无状态 API 服务 → 轮询/随机最简单
- 会话保持（登录后一直走同一台）→ 一致性哈希 + IP hash
- 缓存场景（Redis 分片、Memcached）→ 一致性哈希，避免扩缩容全量失效
- 机器性能差异大 → 加权轮询或最短响应时间
- 有长连接后端（如 MQ Consumer）→ 最少活跃连接

**Nginx upstream 配置常见算法**：
- `ip_hash`：同一 IP 命中同一后端（会话保持）
- `least_conn`：最少连接
- `hash $uri`：一致性哈希（Nginx 1.9.0+）
- `balance`：阿里云自研的一致性哈希

### STEP 4 · 简化

> **口诀**：3 层位置（网络/应用/客户端）+ 7 种算法；缓存场景用一致性哈希+虚拟节点；取模不适合扩缩容。

## 常见误区（从面试记录提炼）

- **误区 1**：只列"取模、范围、随机、一致性哈希"，没明确轮询/加权轮询→ 正确：轮询和加权轮询是默认算法，所有 LB 都支持
- **误区 2**：把"性能最佳、响应最佳、负载均衡"当算法名→ 正确：这些是描述词，不是具体算法
- **误区 3**：没区分客户端 LB 和服务端 LB → 正确：客户端 LB（Ribbon）无第三方但每个客户端要实现；服务端 LB（Nginx）集中但多一跳

## 延伸追问（面试追问预演）

1. **一致性哈希如何解决数据倾斜？**
   - 要点：引入虚拟节点，每个真实节点在环上生成 100-200 个虚拟节点，让数据分布更均匀。扩容时新节点抢占原有虚拟节点的数据范围。
2. **取模在节点扩缩容时有什么问题？**
   - 要点：节点数变了几乎所有 key 都要重分，缓存全失效，所以缓存场景不用取模。
3. **客户端 LB 和服务端 LB 有什么区别？**
   - 要点：客户端 LB 无第三方，性能高，但每个客户端都要实现；服务端 LB 集中在网关/LB，运维简单，但多一跳。Service Mesh（Istio）把客户端 LB 下沉到 sidecar。
4. **Nginx 配置 upstream 时如何选算法？**
   - 要点：`ip_hash` 让同一 IP 命中同一后端（会话保持）；`least_conn` 最少连接；`hash $uri` 一致性哈希（Nginx 1.9.0+）；`balance` 是阿里云自研的一致性哈希。

## 速查表

```
3 层位置：网络层（LVS/F5）/ 应用层（Nginx/HAProxy）/ 客户端（Ribbon/LoadBalancer/Dubbo）
7 大算法：轮询 / 加权轮询 / 随机 / 加权随机 / 一致性哈希 / 最短响应时间 / 最少活跃连接
一致性哈希：哈希环 + 顺时针 + 虚拟节点（150/节点）
取模死穴：扩缩容导致所有 key 重分，缓存全失效
典型场景：无状态→轮询；会话保持→一致性哈希+IP hash；缓存→一致性哈希；异构→加权；长连接→最少活跃连接
Nginx upstream：ip_hash / least_conn / hash $uri / balance
```

## 关联题目（题库）

- [x] 《什么是负载均衡，有哪些常见算法？》—— 2026-09-27 Round 1 Q7, 评分 ⭐⭐⭐

## 关联知识

- [Nacos 核心机制](./nacos-core.md)
- [微服务调用方式全景](./microservice-communication.md)

## Anki 候选卡片

1. **正**：负载均衡 3 层位置？**反**：网络层（LVS/F5）+ 应用层（Nginx/HAProxy）+ 客户端（Ribbon/Spring Cloud LoadBalancer/Dubbo Consumer）
2. **正**：负载均衡 7 大经典算法？**反**：轮询 / 加权轮询 / 随机 / 加权随机 / 一致性哈希 / 最短响应时间 / 最少活跃连接
3. **正**：取模在扩缩容时的问题？**反**：节点数变了几乎所有 key 都要重分，导致缓存全失效，不适合缓存场景
4. **正**：一致性哈希原理？**反**：哈希环（0~2^32）+ 节点映射到环 + 请求顺时针取第一个节点；扩缩容只影响 N/K 请求
5. **正**：一致性哈希如何解决数据倾斜？**反**：引入虚拟节点，每个真实节点在环上生成 100-200 个虚拟节点，让数据分布更均匀
6. **正**：客户端 LB 和服务端 LB 区别？**反**：客户端 LB 无第三方但每个客户端要实现；服务端 LB 集中但多一跳；Service Mesh 把客户端 LB 下沉到 sidecar

---

*最后更新：2026-09-27*
