Files
autumn-recruitment/05.架构/service-governance/负载均衡算法_test.md
T

143 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 个要点即可得满分;完全正确需覆盖全部要点。
## 关联笔记
- [[服务注册与发现]]
- [[限流熔断降级]]