负载均衡策略#
一句话答案#
客户端负载均衡策略:轮询(默认)、随机、加权、最少连接、一致性哈希,Spring Cloud LoadBalancer 默认轮询。
核心要点
Spring Cloud LoadBalancer 策略:
- RoundRobin(默认轮询)
- Random(随机)
Dubbo 策略: Random(默认) / RoundRobin / LeastActive / ConsistentHash
关键算法机制(深挖)#
策略名谁都会背,面试官会追「加权轮询怎么不扎堆」「一致性哈希怎么解决倾斜」这些机制题。
平滑加权轮询(Smooth Weighted Round-Robin,Nginx/Dubbo 都用)
普通加权轮询若按 {A:5, B:1, C:1} 直接展开成 A A A A A B C,结果是 5 个请求连续打到 A,瞬时压力扎堆。平滑加权轮询让高权重节点均匀分散:
- 每个节点维护
current_weight,固定权重weight,总权重total。 - 每次选址:① 每个节点
current_weight += weight;② 选current_weight最大的节点;③ 被选中节点current_weight -= total。
以 {A:5, B:1, C:1}(total=7)为例,7 次选出的序列是 A B A C A A A——A 被均匀打散而非连续 5 次。为什么不扎堆:被选中后减去 total 把自己「压到谷底」,要重新攒够权重才会再被选中,从而和其他节点交错。
一致性哈希 + 虚拟节点(为何解决倾斜)
一致性哈希把节点和请求 key 都哈希到一个 0~2³² 的环上,请求顺时针找到第一个节点。问题:节点数少时,几个真实节点在环上分布不均,会有的区间大有的区间小,导致负载倾斜;且某节点下线,它那一整段流量全压到顺时针下一个节点。
虚拟节点:把每个物理节点映射成 N 个虚拟节点(如 nodeA#1、nodeA#2…哈希后散落在环上多处)。虚拟节点越多,环上分布越均匀,每个物理节点承担的区间被打散成很多小段——既降低倾斜,又让某节点下线时它的流量分散到多个其他节点而非全压给一个。Dubbo ConsistentHash 默认每个 invoker 160 个虚拟节点。
Dubbo LeastActive:active 计数在 Filter 里加减
最少活跃调用数 = 选当前并发调用数最少的节点(响应快的节点 active 低,会拿到更多请求,天然倾向快节点)。这个 active 计数靠 ActiveLimitFilter/RpcStatus 维护:调用前 active++,调用返回(成功或异常)后 active—。所以 active 反映的是「此刻正在途中的请求数」,处理慢的节点 active 累积得高,自然少被选。
P2C(Power of Two Choices,随机选两个比负载)
随机挑两个节点,比较二者负载(连接数/active/RT)选较优的那个。相比「全局选最小负载」省去维护全局有序结构的开销,又比纯随机均衡得多——数学上「随机两选一」能把最大负载从 O(logN) 降到 O(loglogN),是 gRPC、新版微服务 LB 的主流默认(兼顾低开销与高均衡)。
面试回答(2分钟版)
微服务的负载均衡分服务端和客户端两种。服务端负载均衡由独立的 LB 节点如 Nginx 或 F5 统一转发,集中式管理但有单点风险和额外一跳。客户端负载均衡是微服务主流方案,每个消费者从注册中心拉取服务实例列表,在本地根据策略选择调用目标,少了一跳更灵活。Spring Cloud LoadBalancer 提供 RoundRobin 轮询和 Random 随机两种策略,默认轮询;Dubbo 更丰富,默认 Random 随机,还支持 RoundRobin 轮询、LeastActive 最少活跃调用数和 ConsistentHash 一致性哈希。轮询适合实例性能相近的场景,加权轮询适合实例配置不同的场景,最少连接适合长连接或处理时间差异大的场景,一致性哈希适合需要会话亲和或提高本地缓存命中率的场景。客户端 LB 更适合微服务架构因为服务列表直接从 Nacos 等注册中心获取,无需单独部署 LB 节点,每个消费者独立决策不存在单点问题。
追问与易错
追问方向:
- “客户端和服务端 LB 区别?”→ 客户端 LB(如 Ribbon/LoadBalancer)在调用方本地维护服务列表自行选择节点,去中心化无单点;服务端 LB(如 Nginx/F5)集中代理所有请求,配置简单但有单点瓶颈
- “一致性哈希什么场景用?”→ 需要会话亲和性(同一用户请求落到同一节点)的场景,如本地缓存命中率优化、WebSocket 长连接固定节点;避免节点增减导致大量缓存失效
- “LB 怎么做健康检查?”→ 主动健康检查:定时发心跳/HTTP 探针到后端节点,连续失败则摘除;被动健康检查:统计实际请求的错误率,超阈值自动摘除;两者配合使用效果最好
- “加权轮询怎么避免大权重节点请求扎堆?”→ 用平滑加权轮询:每轮每个节点 current_weight+=weight,选 current 最大者,选中后 current-=总权重把自己压到谷底,要重新攒权重才能再被选,从而把高权重节点均匀打散而非连续打满
- “一致性哈希虚拟节点为什么能解决倾斜?”→ 节点少时真实节点在哈希环上分布不均会倾斜,且某节点下线流量全压给顺时针下一个;把每个物理节点映射成 N 个虚拟节点散落环上,分布更均匀、下线时流量分散到多个节点。Dubbo 默认 160 个虚拟节点
- “LeastActive 的 active 计数怎么来的?”→ 在 Filter(RpcStatus)里维护,调用前 active++、返回后 active—,反映此刻在途请求数,慢节点 active 累积高自然少被选
- “P2C 是什么?”→ Power of Two Choices,随机挑两个节点比负载选较优者,省去全局有序结构开销又比纯随机均衡得多,是 gRPC 等新版 LB 的主流默认
易错点:
- ❌ 轮询就是最公平的——节点性能不同需加权
- ❌ 客户端 LB 不如服务端——微服务场景更灵活