LoadBalancer 和 Ribbon 的区别是什么?为什么用它替代 Ribbon?

一则或许对你有用的小广告

欢迎 加入小哈的星球 ,你将获得: 专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目: 《Spring AI 项目实战(问答机器人、RAG 增强检索、联网搜索)》 正在持续爆肝中,基于 Spring AI + Spring Boot3.x + JDK 21...点击查看;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot3.x + JDK 17...点击查看项目介绍; 演示链接: http://116.62.199.48:7070/;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/

面试考察点

  1. 框架演进认知:面试官不仅仅是想知道 LoadBalancer 和 Ribbon 的功能差异,更是想考察你是否关注 Spring Cloud 生态的版本演进,是否了解从 Netflix OSS 到 Spring Cloud 自研组件的迁移脉络。

  2. 负载均衡原理:考察你对客户端负载均衡的理解深度——是否清楚服务发现、服务选择、健康检查这些核心机制。

  3. 技术选型意识:能否说清楚为什么官方要 "弃 Ribbon 转 LoadBalancer",这背后反映的是你对技术生命周期和维护策略的判断力。

核心答案

Ribbon 是 Netflix 开源的客户端负载均衡组件,Spring Cloud LoadBalancer 是 Spring 官方推出的替代方案。 替换的根本原因是 Ribbon 已进入维护模式(Maintenance Mode),不再积极更新。

核心区别一览:

对比维度RibbonSpring Cloud LoadBalancer
维护方Netflix(已停更)Spring 官方(持续迭代)
状态维护模式,不再新增功能活跃开发中
所属生态Netflix OSSSpring Cloud 自研
缓存机制自带 Spring 缓存(SpringClientFactory依赖 Spring Cache(如 Caffeine)
配置方式基于 .properties / .yml 细粒度配置基于 LoadBalancerClient 配置
依赖体积较重,依赖较多轻量,核心包很小
Reactive 支持不支持天然支持 Reactive(WebClient)
默认集成Spring Cloud 2020.x 之前Spring Cloud 2020.x 及之后

一句话总结:Ribbon 已停更 "退休",LoadBalancer 是 Spring 官方推出的 "继任者",功能更轻量、拥抱 Reactive,新项目必须用 LoadBalancer。

深度解析

一、为什么 Ribbon 被淘汰?

Ribbon 被替换不是因为它不好用,而是 Netflix OSS 全线停更带来的连锁反应。

上图展示了 Spring Cloud Netflix 组件的 "退役" 时间线。关键要点:

  • 2015 年前后,Spring Cloud Netflix 是微服务领域的事实标准,Eureka + Ribbon + Hystrix + Zuul 组合几乎成了 "标配"。
  • 2018 ~ 2019 年,Netflix 陆续宣布核心组件进入维护模式,不再积极开发新功能。
  • 2020 年,Spring 官方在 Spring Cloud 2020.x(代号 Ilford)中正式移除了 Netflix 依赖,推出了自研替代方案。
  • 核心逻辑:Spring 官方不可能让自己的生态依赖一个不再更新的第三方库,所以必须寻找或自研替代方案。

二、两者架构对比

从架构图可以看出两者的设计思路差异:

  • Ribbon:采用自己的接口体系(ServerListIRuleIPing),与 Netflix 生态深度绑定。
  • LoadBalancer:采用 Spring 风格的接口设计(ServiceInstanceListSupplierReactiveLoadBalancer),与 Spring 生态无缝融合,并且天然支持响应式编程。

三、负载均衡策略对比

两者都支持常见的负载均衡策略,但实现方式不同:

策略Ribbon 实现LoadBalancer 实现
轮询RoundRobinRuleRoundRobinLoadBalancer(默认)
随机RandomRuleRandomLoadBalancer
加权WeightedResponseTimeRule需自定义或配合 Nacos 权重
最佳可用BestAvailableRule需自定义
哈希无内置无内置

LoadBalancer 默认使用轮询策略,如果需要切换策略,可以通过自定义 LoadBalancerClient 配置来实现。

四、代码实战对比

Ribbon 方式(旧)

// application.yml 配置
// user-service:
//   ribbon:
//     NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

// 直接使用 @LoadBalanced RestTemplate
@Configuration
public class RibbonConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

// 调用
@RestController
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    public User getUser(Long userId) {
        // Ribbon 拦截请求,根据服务名选择实例
        return restTemplate.getForObject(
            "http://user-service/api/users/" + userId,
            User.class
        );
    }
}

LoadBalancer 方式(新)

// 1. 添加依赖(Spring Cloud 2020.x+ 自动包含)
// spring-cloud-starter-loadbalancer

// 2. 使用方式几乎一致
@Configuration
public class LoadBalancerConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    // 3. 也可以搭配 WebClient(Reactive 方式)
    @Bean
    @LoadBalanced
    public WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}

// 调用方式不变
@RestController
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private WebClient.Builder webClientBuilder;

    // 同步调用
    public User getUser(Long userId) {
        return restTemplate.getForObject(
            "http://user-service/api/users/" + userId,
            User.class
        );
    }

    // Reactive 调用(Ribbon 做不到)
    public Mono<User> getUserReactive(Long userId) {
        return webClientBuilder.build()
            .get()
            .uri("http://user-service/api/users/" + userId)
            .retrieve()
            .bodyToMono(User.class);
    }
}

可以看到,迁移成本其实很低——@LoadBalanced 注解照用,调用方式不变。LoadBalancer 还额外支持 WebClient 的响应式调用。

五、迁移注意事项

如果你从 Ribbon 迁移到 LoadBalancer,需要注意以下几点:

  1. 排除 Ribbon 依赖:确保 pom.xml 中不再引入 spring-cloud-starter-netflix-ribbon,否则可能与 LoadBalancer 产生冲突。

  2. 缓存配置:Ribbon 自带缓存,而 LoadBalancer 需要显式引入 Spring Cache 实现(如 Caffeine):

    <dependency>
        <groupId>com.github.ben-manes.caffeine</groupId>
        <artifactId>caffeine</artifactId>
    </dependency>
    
  3. 自定义策略:Ribbon 通过配置文件切换策略(NFLoadBalancerRuleClassName),LoadBalancer 需要通过 Java 配置类自定义 ReactiveLoadBalancer 实现。

  4. 健康检查:Ribbon 通过 IPing 内置实现,LoadBalancer 需要配合服务注册中心(如 Nacos)的健康检查机制。

面试高频追问

  1. 追问一:LoadBalancer 支持哪些负载均衡策略?如何自定义?

    • 内置轮询(默认)和随机两种。自定义策略需要实现 ReactorServiceInstanceLoadBalancer 接口,注册为 @Bean 即可。
  2. 追问二:客户端负载均衡和服务端负载均衡有什么区别?

    • 客户端负载均衡(Ribbon / LoadBalancer):由调用方自己选择服务实例,不需要中间代理。服务端负载均衡(Nginx / F5):由代理服务器选择后端实例。前者性能更好(少一跳),后者与语言无关。
  3. 追问三:Spring Cloud 2020.x 之后还有哪些 Netflix 组件被替换了?

    • Ribbon → LoadBalancer,Hystrix → Sentinel / Resilience4J,Zuul → Spring Cloud Gateway。Eureka 暂时保留但仍可用,推荐迁移到 Nacos。

常见面试变体

  • 变体一:"Spring Cloud 为什么要替换掉 Ribbon?"
  • 变体二:"说说 Spring Cloud 版本演进中组件的变化。"
  • 变体三:"客户端负载均衡的原理是什么?"
  • 变体四:"如何在 Spring Cloud 中自定义负载均衡策略?"

记忆口诀

Ribbon 已退休,LoadBalancer 接班:Ribbon 停更是因为 Netflix OSS 全线停更,不是 Ribbon 自身的问题。新项目直接用 LoadBalancer,老项目迁移只需换依赖、加缓存、调策略,三步搞定。记住迁移三件事:排依赖、加缓存、改策略

总结

Ribbon 被 LoadBalancer 替代的根本原因是 Netflix OSS 生态全线停更,Spring 官方必须掌握核心组件的主动权。LoadBalancer 更轻量、拥抱 Reactive、与 Spring 生态无缝集成,是 Spring Cloud 2020.x 及之后版本的默认负载均衡方案。迁移成本低,新项目直接用 LoadBalancer 即可。