负载均衡 Ribbon/LoadBalancer?

2025年 阅读约 15 分钟 面试指南 · Spring Cloud

深入解析负载均衡:Ribbon vs Spring Cloud LoadBalancer、常见负载均衡算法(轮询/随机/加权/一致性哈希)、自定义负载均衡策略、客户端 vs 服务端负载均衡,附面试模拟问答。

一句话总结

负载均衡是将请求均匀分发到多个服务实例上,避免单点过载。分两种:服务端负载均衡(Nginx,客户端 → LB → 服务)和客户端负载均衡(Ribbon/LoadBalancer,客户端自己选实例)。Ribbon 已进入维护模式,Spring Cloud 官方推荐 Spring Cloud LoadBalancer。常见算法:轮询(Round Robin)、随机(Random)、加权(Weighted)、最少连接(Least Connections)、一致性哈希(Consistent Hash)。

初级理解

客户端 vs 服务端负载均衡

对比维度客户端负载均衡服务端负载均衡
实现Ribbon、LoadBalancerNginx、F5、HAProxy
位置服务消费者内部独立中间件
服务列表从注册中心获取手动配置
优点无单点、灵活集中管理、功能强
缺点与语言绑定有单点风险

中级深入

常见负载均衡算法

# 1. 轮询(Round Robin) # 依次分配:实例1 → 实例2 → 实例3 → 实例1... # 优点:简单、绝对均匀 # 缺点:不考虑服务器性能差异 # 2. 随机(Random) # 随机选择一个实例 # 优点:简单 # 缺点:可能不均匀 # 3. 加权轮询(Weighted Round Robin) # 根据权重分配:权重高的实例分配更多请求 # 适用:服务器性能不一致的场景 # 4. 最少连接(Least Connections) # 选择当前连接数最少的实例 # 适用:长连接场景 # 5. 一致性哈希(Consistent Hash) # 根据请求参数(如用户 ID)哈希到固定实例 # 优点:同一用户请求始终到同一实例 # 适用:有状态服务、缓存亲和性

LoadBalancer 使用

# Spring Cloud LoadBalancer 配置 spring: cloud: loadbalancer: ribbon: enabled: false # 禁用 Ribbon cache: enabled: true ttl: 35s # 服务列表缓存时间 # 自定义负载均衡策略 @Configuration public class LoadBalancerConfig { @Bean public ReactorLoadBalancer<ServiceInstance> customLoadBalancer( Environment env, LoadBalancerClientFactory factory) { String name = env.getProperty("loadbalancer.client.name"); return new RoundRobinLoadBalancer( factory.getLazyProvider(name, ServiceInstanceListSupplier.class), name); } }

高级拓展

一致性哈希原理

# 一致性哈希 # 1. 将哈希空间组织成环(0 ~ 2^32-1) # 2. 每个节点(服务实例)映射到环上的一个点 # 3. 请求根据 key 哈希,顺时针找到第一个节点 # 优点:节点增减时只影响相邻节点 # 传统哈希:节点数变化 → 几乎所有 key 重新映射 # 一致性哈希:节点数变化 → 只影响约 1/n 的 key # 虚拟节点:解决数据倾斜 # 每个物理节点映射多个虚拟节点到环上 # 使数据分布更均匀

Ribbon 原理

# Ribbon 核心组件 # 1. ServerList:服务列表(从注册中心获取) # 2. ServerListFilter:过滤不健康的实例 # 3. IRule:负载均衡策略 # 4. IPing:健康检查 # Ribbon 执行流程 # 1. 从注册中心获取服务列表 → ServerList # 2. 过滤掉不健康的实例 → ServerListFilter # 3. 根据策略选择一个实例 → IRule # 4. 发起 HTTP 调用 # Ribbon 内置策略 # RoundRobinRule:轮询 # RandomRule:随机 # WeightedResponseTimeRule:根据响应时间加权 # BestAvailableRule:选择并发最小的 # ZoneAvoidanceRule:默认,区域感知

实战场景

场景:自定义一致性哈希策略

# 场景:同一用户请求始终路由到同一实例 # 用于缓存亲和性、会话保持 # 自定义 LoadBalancer 配置 @Configuration public class ConsistentHashConfig { @Bean public ReactorLoadBalancer<ServiceInstance> consistentHashLoadBalancer( Environment env, LoadBalancerClientFactory factory) { String name = env.getProperty("loadbalancer.client.name"); return new ConsistentHashLoadBalancer( factory.getLazyProvider(name, ServiceInstanceListSupplier.class), name); } } # 使用 @FeignClient(name = "user-service", configuration = ConsistentHashConfig.class) public interface UserFeignClient { }

面试模拟

面试官:客户端和服务端负载均衡有什么区别?

你:客户端负载均衡在服务消费者内部(Ribbon/LoadBalancer),从注册中心获取服务列表自己选择;服务端负载均衡是独立中间件(Nginx),客户端请求先到 LB 再转发。客户端无单点但和语言绑定,服务端集中管理但有单点风险。

面试官:一致性哈希的原理和优点?

你:将哈希空间组织成环,节点和请求都映射到环上,请求顺时针找第一个节点。优点是节点增减时只影响相邻节点,不会导致大量缓存失效。通过虚拟节点解决数据倾斜问题。