Skip to content

Ribbon 与 LoadBalancer:客户端负载均衡

负载均衡是微服务架构中不可或缺的一环。当一个服务有多个实例时,负载均衡器决定将请求发送给哪个实例。在 Spring Cloud 生态中,经历了从 Ribbon 到 Spring Cloud LoadBalancer 的演进。

一、为什么需要客户端负载均衡?

服务端负载均衡(Nginx):
客户端 → [Nginx 中心节点] → 实例1 / 实例2 / 实例3
特点:客户端不知道后端实例,Nginx 是单点瓶颈

客户端负载均衡(Ribbon/LoadBalancer):
客户端 → 从注册中心拉取实例列表 → 自己选一个 → 直连实例
特点:无中心节点,更灵活,微服务内部调用标配

在微服务架构中,服务间调用(如订单服务调用库存服务)走的是内网,不需要经过 Nginx。客户端负载均衡让调用方自己从注册中心获取实例列表并选择,省去了中心化负载均衡器的瓶颈。

二、Ribbon:Netflix 时代的经典

2.1 Ribbon 是什么

Ribbon 是 Netflix 开源的客户端负载均衡器,曾经是 Spring Cloud 生态中服务调用的标配。它内嵌在 Feign 和 RestTemplate 中,自动为服务调用提供负载均衡能力。

2.2 Ribbon 核心组件

组件接口说明
ServerList获取服务实例列表从注册中心(Eureka/Nacos)拉取
IRule负载均衡策略轮询、随机、加权、最小连接数等
IPing健康检查判断实例是否存活
ServerListFilter实例过滤过滤掉不健康的实例
ILoadBalancer协调器整合以上组件,对外提供 chooseServer()

2.3 内置负载均衡策略

策略类说明
RoundRobinRule轮询,依次选择(默认)
RandomRule随机选择
WeightedResponseTimeRule按响应时间加权,响应越快权重越高
BestAvailableRule选择并发请求最少的实例
RetryRule失败后重试,换一个实例
AvailabilityFilteringRule过滤掉熔断或高并发的实例
ZoneAvoidanceRule按区域就近选择

2.4 Ribbon 的现状

2020 年,Netflix 宣布 Ribbon 进入维护模式(不再添加新功能,只修 Bug)。Spring Cloud 官方随即推出了替代方案——Spring Cloud LoadBalancer。目前新项目已不再推荐使用 Ribbon。

三、Spring Cloud LoadBalancer:官方替代品

3.1 与 Ribbon 的对比

维度RibbonSpring Cloud LoadBalancer
维护方Netflix(已停维)Spring 官方(活跃)
编程模型阻塞式响应式(Reactive)
性能一般更好(非阻塞)
与 Spring Cloud 集成原生(旧版)原生(新版)
自定义策略实现 IRule 接口实现 ReactorLoadBalancer 接口
Spring 官方推荐

3.2 工作原理

1. 服务启动时,注册到 Nacos


2. @FeignClient 标注的服务调用


3. Feign 拦截调用,委托给 LoadBalancer


4. LoadBalancer 从 Nacos 获取目标服务的实例列表


5. 根据负载均衡策略选择一个实例


6. 构造 HTTP 请求,发送到选中的实例


7. 如果调用失败,根据重试策略决定是否换一个实例重试

3.3 内置策略

策略说明适用场景
RoundRobinLoadBalancer轮询(默认)实例性能一致
RandomLoadBalancer随机选择简单场景
NacosLoadBalancer基于 Nacos 权重使用 Nacos 注册中心时

3.4 配置示例

yaml
spring:
  cloud:
    loadbalancer:
      retry:
        enabled: true                # 开启重试,失败后换实例
      cache:
        enabled: true                # 开启实例列表缓存
        ttl: 35s                     # 缓存过期时间
      nacos:
        enabled: true                # 启用 Nacos 权重策略

3.5 自定义策略

java
@Configuration
public class CustomLoadBalancerConfig {

    @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);
    }
}

四、Ribbon → LoadBalancer 迁移要点

如果你的项目从旧版 Spring Cloud 升级,需要注意以下变化:

迁移项Ribbon 写法LoadBalancer 写法
依赖spring-cloud-starter-netflix-ribbonspring-cloud-starter-loadbalancer(已内置)
策略配置order-service.ribbon.NFLoadBalancerRuleClassName@LoadBalancerClient 注解
自定义策略implements IRuleimplements ReactorLoadBalancer
重试配置ribbon.MaxAutoRetriesspring.cloud.loadbalancer.retry.enabled

五、面试要点

Q:Ribbon 和 Spring Cloud LoadBalancer 的区别?

  1. Ribbon 是 Netflix 开源,已停维;LoadBalancer 是 Spring 官方,活跃维护
  2. Ribbon 是阻塞式 IO;LoadBalancer 基于响应式编程,非阻塞,性能更好
  3. Ribbon 策略更丰富(7 种内置);LoadBalancer 策略较少但够用,且支持自定义
  4. 新项目直接用 LoadBalancer,旧项目在使用 Ribbon 也无需急于迁移

Q:Feign 中如何选择负载均衡策略?

Feign 默认使用 LoadBalancer 的轮询策略。如需自定义,通过 @LoadBalancerClient 注解指定配置类,或直接配置 spring.cloud.loadbalancer.nacos.enabled=true 启用 Nacos 权重策略。

Q:客户端负载均衡 vs 服务端负载均衡,微服务中为什么用客户端?

客户端负载均衡去掉了中心化 LB 的瓶颈,调用方直连目标实例,减少一次网络跳转。而且客户端知道所有实例的状态,可以做更智能的负载均衡决策(如最小连接数)。服务端负载均衡(Nginx)更适合对外暴露的 API 入口。