Spring Cloud LoadBalancer 使用指南(从入门到实战)

Spring Cloud LoadBalancer(SCLB)是 Spring Cloud 官方提供的客户端负载均衡器,替代了老旧的 Ribbon(已停止维护)。它的核心价值是:在微服务架构中,客户端(如订单服务)调用其他服务(如库存服务)时,自动从服务注册中心(Nacos/Eureka)获取服务实例列表,通过负载均衡算法选择一个实例发起请求,实现「服务集群的负载分发」和「故障自动切换」。

本文基于 Spring Cloud Alibaba 环境(适配 Nacos 服务发现),从「入门配置→核心功能→进阶实战→生产优化」逐步讲解,帮你快速掌握 LoadBalancer 的使用。

一、入门:快速集成(5 分钟上手)

1. 核心依赖(无需额外引入,已包含在常用 Starter 中)

在微服务客户端(如 order-server)的 pom.xml 中,只要引入了 spring-cloud-starter-alibaba-nacos-discovery 或 spring-cloud-starter-openfeign,会自动依赖 LoadBalancer 核心包(Spring Cloud 2020+ 版本默认集成):

<!-- Nacos 服务发现(自动依赖 LoadBalancer) -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- OpenFeign(自动依赖 LoadBalancer,用于服务间调用) -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2. 基础配置(application.yml)

无需额外配置,LoadBalancer 会自动与 Nacos 集成,从注册中心拉取服务实例。核心配置仅需确保「服务发现启用」:

spring:
  application:
    name: order-server # 当前服务名
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848 # Nacos 注册中心地址
    # LoadBalancer 可选配置(默认无需配置,使用默认算法)
    loadbalancer:
      # 禁用缓存(开发环境用,生产环境建议启用)
      cache:
        enabled: false
      # 连接超时(默认 1000ms)
      client:
        connect-timeout: 2000
        # 读取超时(默认 5000ms)
        read-timeout: 6000

3. 两种使用场景(Feign 调用 + RestTemplate 调用)

LoadBalancer 支持两种客户端调用方式,均会自动触发负载均衡:

(1)场景 1:OpenFeign 调用(推荐,微服务主流方式)

Feign 是声明式 HTTP 客户端,与 LoadBalancer 无缝集成,无需手动处理负载均衡逻辑:

  • 步骤 1:启动类添加 @EnableFeignClients 注解,启用 Feign:
    @SpringBootApplication
    @EnableDiscoveryClient // 启用 Nacos 服务发现
    @EnableFeignClients // 启用 Feign 客户端
    public class OrderApplication {
        public static void main(String[] args) {
            SpringApplication.run(OrderApplication.class, args);
        }
    }
    
  • 步骤 2:定义 Feign 接口(指定目标服务名 stock-server):
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    // name = 目标服务名(必须与 Nacos 中注册的服务名一致)
    @FeignClient(name = "stock-server")
    public interface StockFeignClient {
    
        // 对应 stock-server 的接口路径和参数
        @GetMapping("/stock/deduct/{productId}")
        String deductStock(@PathVariable("productId") Long productId);
    }
    
  • 步骤 3:在业务代码中注入 Feign 接口,直接调用(自动负载均衡):
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    import javax.annotation.Resource;
    
    @RestController
    public class OrderController {
    
        @Resource
        private StockFeignClient stockFeignClient;
    
        @GetMapping("/order/create/{productId}")
        public String createOrder(@PathVariable Long productId) {
            // 调用 stock-server,LoadBalancer 自动选择实例
            String stockResult = stockFeignClient.deductStock(productId);
            return "订单创建成功!" + stockResult;
        }
    }
    
(2)场景 2:RestTemplate 调用(手动配置)

若不使用 Feign,可通过 @LoadBalanced 注解标记 RestTemplate,使其具备负载均衡能力:

  • 步骤 1:配置 RestTemplate 并添加 @LoadBalanced
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    @Configuration
    public class RestTemplateConfig {
    
        @Bean
        @LoadBalanced // 关键:启用 LoadBalancer 负载均衡
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    }
    
  • 步骤 2:业务代码中使用 RestTemplate 调用(URL 填写服务名,而非 IP: 端口):
    @RestController
    public class OrderController {
    
        @Resource
        private RestTemplate restTemplate;
    
        @GetMapping("/order/create/{productId}")
        public String createOrder(@PathVariable Long productId) {
            // 注意:URL 中用服务名 stock-server 替代 IP:端口
            String url = "http://stock-server/stock/deduct/" + productId;
            // LoadBalancer 自动解析服务名,选择实例转发
            String stockResult = restTemplate.getForObject(url, String.class);
            return "订单创建成功!" + stockResult;
        }
    }
    

4. 测试验证

  • 启动 Nacos 注册中心;
  • 启动 2 个 stock-server 实例(端口分别为 8020、8021,服务名均为 stock-server);
  • 启动 order-server,多次访问 http://localhost:8010/order/create/1
  • 观察 stock-server 的日志,会发现两个实例交替接收请求(默认轮询算法)。

二、核心概念:负载均衡算法(默认 + 自定义)

LoadBalancer 的核心是「负载均衡算法」,即如何从服务实例列表中选择一个实例。Spring Cloud LoadBalancer 提供了默认算法,也支持自定义扩展。

1. 内置默认算法(无需配置,开箱即用)

算法类型适用场景原理
RoundRobinLoadBalancer(轮询)所有实例性能相近,无明显差异按实例顺序依次选择(实例 1→实例 2→实例 1→实例 2...),默认使用该算法。
RandomLoadBalancer(随机)希望请求随机分发,避免单一实例压力集中从实例列表中随机选择一个实例。
ResponseTimeWeightedLoadBalancer(响应时间加权)实例性能差异较大(如部分实例配置更高)响应时间越短的实例,被选中的概率越高(需引入 spring-boot-starter-actuator 收集响应时间)。
切换默认算法(配置文件方式)

在客户端(如 order-server)的 application.yml 中配置,指定全局默认算法:

spring:
  cloud:
    loadbalancer:
      # 切换为随机算法(可选值:round_robin、random、response_time_weighted)
      nimbus:
        rule: random

2. 自定义负载均衡算法(实战场景)

实际项目中,可能需要根据业务场景自定义算法(如「权重负载均衡」「区域亲和性负载均衡」)。以下以「权重算法」为例,讲解自定义步骤:

需求:给不同的 stock-server 实例配置不同权重,权重越高,被选中的概率越大
  • 步骤 1:给 stock-server 实例配置权重(在 Nacos 中设置元数据):

    启动 stock-server 时,通过启动参数指定权重(或在 application.yml 中配置):
    spring:
      cloud:
        nacos:
          discovery:
            server-addr: 127.0.0.1:8848
            metadata:
              weight: 5 # 实例1权重为5(端口8020)
    

        若另一个实例配置 weight: 10(端口 8021),权重比为 1:2。

  • 步骤 2:自定义负载均衡规则(实现 ReactorServiceInstanceLoadBalancer 接口):

    import org.springframework.cloud.client.ServiceInstance;
    import org.springframework.cloud.client.loadbalancer.*;
    import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
    import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
    import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
    import reactor.core.publisher.Mono;
    
    import java.util.List;
    import java.util.Random;
    import java.util.stream.Collectors;
    
    /**
     * 自定义权重负载均衡算法
     */
    public class WeightedLoadBalancer implements ReactorServiceInstanceLoadBalancer {
    
        private final String serviceId; // 目标服务名
        private final Random random; // 随机数生成器
    
        public WeightedLoadBalancer(String serviceId) {
            this.serviceId = serviceId;
            this.random = new Random();
        }
    
        @Override
        public Mono<Response<ServiceInstance>> choose(Request request) {
            // 1. 获取服务实例列表(从 Nacos 拉取)
            ServiceInstanceListSupplier supplier = ServiceInstanceListSupplier.builder()
                    .withServiceId(serviceId)
                    .build();
    
            return supplier.get()
                    .next()
                    .map(this::selectInstanceByWeight);
        }
    
        /**
         * 按权重选择实例
         */
        private Response<ServiceInstance> selectInstanceByWeight(List<ServiceInstance> instances) {
            if (instances.isEmpty()) {
                return new EmptyResponse();
            }
    
            // 2. 过滤出有权重配置的实例(权重≥1)
            List<ServiceInstance> validInstances = instances.stream()
                    .filter(instance -> {
                        String weightStr = instance.getMetadata().get("weight");
                        return weightStr != null && Integer.parseInt(weightStr) > 0;
                    })
                    .collect(Collectors.toList());
    
            if (validInstances.isEmpty()) {
                return new EmptyResponse();
            }
    
            // 3. 计算总权重
            int totalWeight = validInstances.stream()
                    .mapToInt(instance -> Integer.parseInt(instance.getMetadata().get("weight")))
                    .sum();
    
            // 4. 生成随机数,按权重区间选择实例
            int randomNum = random.nextInt(totalWeight);
            int currentWeight = 0;
            for (ServiceInstance instance : validInstances) {
                currentWeight += Integer.parseInt(instance.getMetadata().get("weight"));
                if (randomNum < currentWeight) {
                    return new DefaultResponse(instance);
                }
            }
    
            // 兜底:返回第一个实例
            return new DefaultResponse(validInstances.get(0));
        }
    }
    
  • 步骤 3:配置自定义算法为全局默认规则:

    import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
    import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
    import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.env.Environment;
    
    @Configuration
    public class LoadBalancerConfig {
    
        /**
         * 注册自定义权重负载均衡算法
         */
        @Bean
        public ReactorLoadBalancer<ServiceInstance> weightedLoadBalancer(
                Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
            // 获取目标服务名(从环境变量中读取)
            String serviceId = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
            return new WeightedLoadBalancer(serviceId);
        }
    }
    
  • 步骤 4:测试验证:启动 2 个 stock-server 实例(权重 5 和 10),多次访问 order-server 接口,会发现权重 10 的实例被调用的概率是权重 5 的 2 倍。

三、进阶:核心功能实战(生产必备)

1. 实例健康检查(故障自动剔除)

LoadBalancer 支持「健康检查」,当服务实例不可用时(如宕机、接口报错),自动从实例列表中剔除,避免请求转发到故障实例。

(1)基于 Nacos 健康检查(推荐,无需额外配置)

Nacos 自带服务健康检查机制(默认心跳检测,每 5 秒发送一次心跳),当实例宕机或心跳超时,Nacos 会将其标记为「不健康」,LoadBalancer 从 Nacos 拉取实例时,只会获取「健康实例」。

(2)自定义健康检查(针对接口级健康状态)

若需要更精细的健康检查(如检查实例的 /health 接口是否正常),可集成 Spring Boot Actuator:

  • 步骤 1:添加 Actuator 依赖:
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
  • 步骤 2:配置 Actuator 暴露健康端点:
    management:
      endpoints:
        web:
          exposure:
            include: health # 暴露 /actuator/health 端点
      endpoint:
        health:
          show-details: always # 显示健康详情
    
  • 步骤 3:LoadBalancer 自动关联健康检查(无需额外配置):当实例的 /actuator/health 端点返回 DOWN 时,LoadBalancer 会将其剔除,直到端点返回 UP 才重新加入实例列表。

2. 负载均衡缓存(提升性能)

LoadBalancer 会缓存服务实例列表,避免每次调用都从 Nacos 拉取(减少网络开销)。生产环境建议启用缓存,并配置合理的缓存过期时间:

spring:
  cloud:
    loadbalancer:
      cache:
        enabled: true # 启用缓存(默认 false)
        ttl: 30000 # 缓存过期时间(30秒,默认 30 秒)
      # 缓存键生成器(默认按服务名缓存,可自定义)
      cache-key-generator:
        type: org.springframework.cloud.loadbalancer.core.DefaultCacheKeyGenerator

3. 重试机制(失败自动重试)

当调用某个实例失败时(如网络超时、接口报错),LoadBalancer 支持自动重试到其他健康实例,提升系统可用性。需配合 spring-retry 依赖实现:

  • 步骤 1:添加重试依赖:
    <dependency>
        <groupId>org.springframework.retry</groupId>
        <artifactId>spring-retry</artifactId>
    </dependency>
    
  • 步骤 2:配置重试规则(application.yml):
    spring:
      cloud:
        loadbalancer:
          retry:
            enabled: true # 启用重试(默认 false)
            max-retries-on-next-service: 1 # 切换到下一个实例的重试次数(默认 1)
            max-retries-on-same-service-instance: 0 # 同一实例的重试次数(默认 0,避免重复调用同一实例)
    
  • 步骤 3:Feign 中启用重试(可选,Feign 自带重试机制):
    feign:
      retry:
        enabled: true # 启用 Feign 重试(默认 false)
        max-attempts: 3 # 最大重试次数(包括首次调用)
        period: 1000 # 重试间隔(1秒)
        max-period: 3000 # 最大重试间隔(3秒)
    

4. 针对特定服务配置独立负载均衡规则

全局规则会作用于所有服务调用,若需要给某个服务(如 stock-server)配置独立规则(如随机算法),其他服务仍用默认轮询算法,可通过「服务级配置」实现:

  • 步骤 1:创建服务级配置类(注意:该类不能被 @ComponentScan 扫描到,否则会变成全局规则):
    import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
    import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
    import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
    import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.env.Environment;
    
    // 注意:该类无需添加 @Configuration 到主启动类的扫描路径(可放在单独包下)
    @Configuration
    public class StockServiceLoadBalancerConfig {
    
        @Bean
        public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(
                Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
            String serviceId = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
            // 给 stock-server 配置随机算法
            return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(serviceId, ServiceInstanceListSupplier.class), serviceId);
        }
    }
    
  • 步骤 2:在 Feign 接口中指定该配置类:
    import org.springframework.cloud.openfeign.FeignClient;
    
    // configuration = 指定服务级负载均衡配置类
    @FeignClient(name = "stock-server", configuration = StockServiceLoadBalancerConfig.class)
    public interface StockFeignClient {
        // 接口方法...
    }
    
  • 效果:调用 stock-server 时使用随机算法,调用其他服务(如 user-server)仍使用全局默认轮询算法。

四、生产环境优化与最佳实践

1. 性能优化技巧

  • 启用实例缓存:减少 Nacos 调用次数,提升响应速度;
  • 合理配置超时时间:避免因实例响应缓慢导致客户端阻塞(建议 connect-timeout=2000msread-timeout=5000ms);
  • 禁用不必要的健康检查:若 Nacos 心跳检测已满足需求,可无需额外启用 Actuator 健康检查;
  • 选择合适的负载均衡算法:性能相近的实例用轮询,性能差异大用响应时间加权,需要精准控制用权重算法。

2. 高可用配置

  • 服务实例集群部署:至少部署 2 个实例,避免单点故障;
  • 启用重试机制:确保故障实例能自动切换到健康实例;
  • 配置实例隔离:通过 Nacos 命名空间或分组,将不同环境(开发 / 测试 / 生产)的服务实例隔离,避免跨环境调用。

3. 监控与排查

  • 集成 Prometheus + Grafana:监控 LoadBalancer 的实例选择情况、缓存命中率、重试次数等指标;
  • 开启 Debug 日志:排查负载均衡相关问题(如实例未被选中、重试未触发):

    yaml

    logging:
      level:
        # LoadBalancer 核心日志(DEBUG 级别)
        org.springframework.cloud.loadbalancer: DEBUG
        # Nacos 服务发现日志(DEBUG 级别)
        com.alibaba.cloud.nacos.discovery: DEBUG
    

4. 常见问题排查

(1)负载均衡不生效(请求只转发到一个实例)
  • 检查服务名是否正确:Feign 接口 @FeignClient(name) 必须与 Nacos 中注册的服务名一致(大小写敏感);
  • 检查实例是否健康:Nacos 控制台查看实例是否为「健康」状态;
  • 检查缓存是否启用:开发环境若禁用缓存,需确保每次调用都能拉取最新实例列表。
(2)重试机制不生效
  • 检查是否引入 spring-retry 依赖;
  • 确认重试配置是否正确(spring.cloud.loadbalancer.retry.enabled=true);
  • 检查异常类型:重试仅对「可重试异常」生效(如网络超时、连接拒绝,业务异常如 500 不会重试)。
(3)实例健康但未被选中
  • 检查实例缓存是否过期:若启用缓存,实例状态更新后需等待缓存过期(默认 30 秒);
  • 检查负载均衡规则:是否因算法逻辑导致实例未被选中(如权重算法中权重配置为 0);
  • 检查网络连通性:客户端是否能正常访问实例的 IP: 端口(排除防火墙、网络隔离问题)。

五、总结

Spring Cloud LoadBalancer 是微服务客户端负载均衡的核心组件,具有「轻量、易集成、可扩展」的特点,与 Spring Cloud Alibaba 生态(Nacos、Feign、Sentinel)无缝兼容。

学习路径建议:

  1. 入门:掌握 Feign + LoadBalancer 快速集成,实现基础负载均衡;
  2. 进阶:理解内置算法,实现自定义算法(如权重),配置健康检查和重试;
  3. 生产:优化缓存、超时、重试参数,结合监控工具保障高可用。

最佳实践:在微服务架构中,优先使用「Feign + LoadBalancer」组合实现服务间调用,配合 Nacos 服务发现和 Sentinel 限流熔断,打造稳定、高效的服务调用链路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

canjun_wen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值