143 lines
6.8 KiB
Markdown
143 lines
6.8 KiB
Markdown
|
|
---
|
|||
|
|
tags: [test/review, architecture, arch/microservice, load-balancing]
|
|||
|
|
create time: 2026-08-09 12:00
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# 负载均衡算法 — 测试题
|
|||
|
|
|
|||
|
|
## 概述
|
|||
|
|
本测试覆盖客户端 vs 服务端负载均衡架构、轮询/随机/一致性哈希/最少连接等核心算法、Spring Cloud LoadBalancer 实现原理以及加权轮询的工程实现。共 10 道题目(6 选择 + 3 填空 + 1 简答)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、选择题(6道,由浅入深)
|
|||
|
|
|
|||
|
|
> **难度阶梯**: Q1-Q2 基础概念 → Q3-Q4 核心原理 → Q5-Q6 深入应用/边界场景
|
|||
|
|
|
|||
|
|
### Q1(基础)— 考察定义层面
|
|||
|
|
|
|||
|
|
以下关于客户端负载均衡与服务端负载均衡的说法中,正确的是:
|
|||
|
|
|
|||
|
|
A. 客户端负载均衡延迟更高,因为多了一次网络跳
|
|||
|
|
B. 服务端负载均衡的故障隔离更好——LB 单点故障不影响其他调用
|
|||
|
|
C. 客户端负载均衡需要为每种语言实现 SDK,服务端 LB 协议无关
|
|||
|
|
D. Nginx 是客户端负载均衡的典型代表
|
|||
|
|
|
|||
|
|
### Q2(基础)→
|
|||
|
|
|
|||
|
|
以下哪种负载均衡算法最适合 WebSocket 长连接场景?
|
|||
|
|
|
|||
|
|
A. 简单轮询(Round Robin)
|
|||
|
|
B. 随机法
|
|||
|
|
C. 最少连接数(Least Connections)
|
|||
|
|
D. 一致性哈希
|
|||
|
|
|
|||
|
|
### Q3(进阶)— 核心原理
|
|||
|
|
|
|||
|
|
传统哈希 `hash(instance) % n` 在实例增减时为什么会导致大量请求重新路由?
|
|||
|
|
|
|||
|
|
A. 因为 hash 函数的不均匀性
|
|||
|
|
B. 因为 n 变化后所有 hash 结果对新的 n 取模都变了
|
|||
|
|
C. 因为虚拟节点数量不足
|
|||
|
|
D. 因为 MurmurHash 本身不适合负载均衡
|
|||
|
|
|
|||
|
|
### Q4(进阶)— 比较/辨析
|
|||
|
|
|
|||
|
|
一致性哈希中虚拟节点的主要作用是什么?
|
|||
|
|
|
|||
|
|
A. 提高 hash 值的随机性
|
|||
|
|
B. 解决数据倾斜问题,使物理实例在环上分布更均匀
|
|||
|
|
C. 增加系统容错能力,某节点挂了可以立即接替
|
|||
|
|
D. 减少 hash 冲突的概率
|
|||
|
|
|
|||
|
|
### Q5(深入)— 场景推理
|
|||
|
|
|
|||
|
|
一个微服务有 5 个实例,权重分别为 A=5、B=3、C=2、D=1、E=1(总权重 12)。使用平滑加权轮询算法,第一个被选中的实例一定是:
|
|||
|
|
|
|||
|
|
A. B(权重 3)
|
|||
|
|
B. C(权重 2)
|
|||
|
|
C. A(权重 5)
|
|||
|
|
D. 无法确定,取决于初始 current_weight
|
|||
|
|
|
|||
|
|
### Q6(深入)— 源码级/边界场景
|
|||
|
|
|
|||
|
|
关于 Spring Cloud LoadBalancer,以下说法哪个是正确的?
|
|||
|
|
|
|||
|
|
A. 它内置了重试和熔断能力
|
|||
|
|
B. 基于 Reactor 响应式编程,返回 Flux<ServiceInstance>
|
|||
|
|
C. 默认使用一致性哈希算法
|
|||
|
|
D. 只支持 HTTP 协议的实例选择
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、填空题(3道)
|
|||
|
|
|
|||
|
|
### F1 — 填空1
|
|||
|
|
|
|||
|
|
一致性哈希将 hash 值空间映射到环上(0 ~ _____),服务和请求都 hash 到环上的同一点,请求顺时针找到最近的实例。移除一个实例只影响其相邻的两个虚拟节点范围,而非全部数据。
|
|||
|
|
|
|||
|
|
> **提示**: 回忆原文中提到的一致性哈希环的范围上限。
|
|||
|
|
|
|||
|
|
### F2 — 填空2
|
|||
|
|
|
|||
|
|
一致性哈希中,每个物理实例对应的虚拟节点数 k 通常取 _____~_____。如果实例频繁增删(每几分钟变一次),k 要调得更大(500+)才能维持稳定性,但会增加内存开销。
|
|||
|
|
|
|||
|
|
> **提示**: 原文中有一个具体的数值范围。
|
|||
|
|
|
|||
|
|
### F3 — 填空3
|
|||
|
|
|
|||
|
|
Nginx 的 smooth weighted round robin 算法中,每次选出 current_weight 最大的实例后,执行 `selected.CurWeight -= _____`,保证长期均衡。
|
|||
|
|
|
|||
|
|
> **提示**: 减去的应该是总权重,这样每个实例的 CurWeight 会在一个周期内回到初始状态。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、简答题(1道)
|
|||
|
|
|
|||
|
|
### S1
|
|||
|
|
|
|||
|
|
某电商大促场景中,你有 10 个商品推荐服务实例,其中 3 台是高性能机器(容量大),7 台是普通机器(容量小)。流量高峰时要求充分利用高性能机器的资源。请说明你会选用哪种负载均衡算法,如何配置参数,并解释为什么不用简单轮询或随机法。
|
|||
|
|
|
|||
|
|
> **答题框架提示**:
|
|||
|
|
> 1. 分析场景的核心矛盾(规格差异)
|
|||
|
|
> 2. 推荐算法并说明理由
|
|||
|
|
> 3. 给出具体配置思路
|
|||
|
|
> 4. 讨论边界情况
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 参考答案与解析
|
|||
|
|
|
|||
|
|
### 选择题答案
|
|||
|
|
|
|||
|
|
| 题号 | 正确答案 | 解析 |
|
|||
|
|
|------|---------|------|
|
|||
|
|
| Q1 | C | A 错:客户端 LB 少一次网络跳所以延迟低;B 错:LB 单点故障影响全部请求,故障隔离差;D 错:Nginx 是服务端 LB。只有 C 正确——客户端 LB 需要各语言的 SDK(如 Spring Cloud LoadBalancer for Java)。 |
|
|||
|
|
| Q2 | C | WebSocket 长连接场景下不同连接的持续时间差异大,最少连接数能保证新请求发给当前活跃连接最少的实例,避免某个实例堆积大量长连接而其他实例闲置。 |
|
|||
|
|
| Q3 | B | 当实例数从 n 变为 n±1 时,几乎所有 key 的 hash(key) % new_n 都会不同于原来的结果,导致约 (n-1)/n 的数据需要迁移。这就是一致性哈希要解决的问题。 |
|
|||
|
|
| Q4 | B | 如果不使用虚拟节点,少数几个物理实例在环上的分布会很不均匀,造成严重的数据倾斜。K=100~200 个虚拟节点让分布趋近均匀。 |
|
|||
|
|
| Q5 | C | 平滑加权轮询第一轮时所有实例的 CurWeight = 0,加上各自 Weight 后 A 的 CurWeight = 5 最大,所以第一轮一定选 A。之后 A 减 12 变为 -7,其他依次加完再选。 |
|
|||
|
|
| Q6 | B | Spring Cloud LoadBalancer 基于 Reactor,返回 Flux<ServiceInstance>。它**不提供**重试和熔断(那是 Resilience4j 的职责),默认策略是 RoundRobinLocator(轮询),不是哈希。 |
|
|||
|
|
|
|||
|
|
### 填空题答案
|
|||
|
|
|
|||
|
|
| 题号 | 答案 | 解析 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| F1 | `2^32`(或"4294967296") | 一致性哈希将 32 位 hash 空间映射为环形地址空间,首尾相接。顺时针寻找最近实例的逻辑确保了实例增减时的最小影响范围。 |
|
|||
|
|
| F2 | `100`;`200` | 这是业界经验值。太少了分布不均,太多了内存占用大且维护代价高。频繁增删场景需要 500+ 的虚拟节点数。 |
|
|||
|
|
| F3 | `totalW`(或"总权重 total_weight") | Nginx 的平滑加权轮询核心公式:cur += weight(累积),选 max 后 selected -= total。这样经过一个完整周期,每个实例被选中的次数恰好等于它的权重占比。 |
|
|||
|
|
|
|||
|
|
### 简答题参考答案
|
|||
|
|
|
|||
|
|
S1:**参考答案要点**:
|
|||
|
|
1. **核心矛盾**:性能差异大的实例不能用简单轮询——每台都会被分到相同数量的请求,导致弱机过载而强机资源浪费。
|
|||
|
|
2. **推荐算法**:加权轮询(Weighted Round Robin)。将 3 台高性能机的权重设为普通机的若干倍(如 3:1 或根据实测 QPS 计算比例),使得长期来看请求按容量比例分配。
|
|||
|
|
3. **不选简单的理由**:简单轮询无视容量差异;随机法在小样本下可能极端不均(连续命中同一个弱机),大促场景不能接受这种不确定性。
|
|||
|
|
4. **边界处理**:需要考虑实例下线时的权重动态调整(Hot Restart 机制)、健康检查剔除故障实例后的自动重新加权。
|
|||
|
|
|
|||
|
|
**评分标准**:答出任意 2 个要点即可得满分;完全正确需覆盖全部要点。
|
|||
|
|
|
|||
|
|
## 关联笔记
|
|||
|
|
- [[服务注册与发现]]
|
|||
|
|
- [[限流熔断降级]]
|