Spring Cloud LoadBalancer案例

wen java案例 1

本文目录导读:

Spring Cloud LoadBalancer案例

  1. 目录导读
  2. 为什么Spring Cloud Netflix Ribbon会被LoadBalancer取代?
  3. 核心概念:负载均衡策略与Reactive支持
  4. 手把手案例:构建基于Nacos的服务发现与LoadBalancer调用
  5. 高级配置:自定义负载均衡规则与重试机制
  6. 性能对比与最佳实践陷阱
  7. 常见问题Q&A(含故障排查)

Spring Cloud LoadBalancer实战指南:从入门到微服务高可用架构

目录导读

  1. 为什么Spring Cloud Netflix Ribbon会被LoadBalancer取代?
  2. 核心概念:负载均衡策略与Reactive支持
  3. 手把手案例:构建基于Nacos的服务发现与LoadBalancer调用
  4. 高级配置:自定义负载均衡规则与重试机制
  5. 性能对比与最佳实践陷阱
  6. 常见问题Q&A(含故障排查)

为什么Spring Cloud Netflix Ribbon会被LoadBalancer取代?

在Spring Cloud 2020.0.0版本后,Netflix Ribbon进入维护模式,官方将Spring Cloud LoadBalancer(SCLB)作为唯一默认客户端负载均衡器,核心原因在于:

  • 拥抱WebFlux:Ribbon基于Servlet阻塞模型,而SCLB原生支持Reactive(响应式)。
  • 架构轻量:SCLB仅依赖Spring Cloud Commons,无需Netflix全家桶。
  • 开放SPI:允许开发者自定义ServiceInstanceListSupplier(服务实例列表供应商)和ReactorLoadBalancer接口。

真实案例:某电商平台在升级Spring Boot 2.7后发现Ribbon触发NoSuchBeanDefinitionException,迁移至SCLB后错误消除,且内存占用降低30%。


核心概念:负载均衡策略与Reactive支持

SCLB内置了三种经典策略:

  • RoundRobinLoadBalancer:轮询(默认)。
  • RandomLoadBalancer:随机。
  • WeightedLoadBalancer:权重(需结合Nacos权重属性)。

关键区别:SCLB返回的是Mono<ServiceInstance>,而非Ribbon的同步ServiceInstance,业务代码若使用RestTemplate,需要通过@LoadBalanced注解桥接;若使用WebClient,则直接支持响应式调用。


手把手案例:构建基于Nacos的服务发现与LoadBalancer调用

环境准备

  • Spring Boot 2.7.18,Spring Cloud 2021.0.8
  • Nacos Server 2.2.3(作为注册中心)

服务提供者(provider-demo)

spring:
  application:
    name: provider-demo
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_ADDR:127.0.0.1:8848}

提供接口/api/hello返回instance-id + port

服务消费者(consumer-demo)

步骤1:引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

步骤2:启用LoadBalancer

@SpringBootApplication
@EnableFeignClients
public class ConsumerApplication {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

步骤3:配置负载均衡策略(application.yml)

spring:
  cloud:
    loadbalancer:
      configurations: health-check # 启用健康检查
      cache:
        enabled: true
        ttl: 5s

步骤4:调用逻辑

@GetMapping("/call")
public String call() {
    // 方式1:RestTemplate
    String result = restTemplate.getForObject("http://provider-demo/api/hello", String.class);
    // 方式2:FeignClient(接口)
    return "负载均衡结果: " + result;
}

启动两个provider实例(端口8081/8082),连续请求/call,观察日志会交替打印不同端口——证明轮询生效。


高级配置:自定义负载均衡规则与重试机制

自定义规则(基于请求头灰度发布)

实现ReactorServiceInstanceLoadBalancer接口,重写choose方法:

@Override
public Mono<Response<ServiceInstance>> choose(Request request) {
    // 获取请求头中的version
    String version = ((RequestDataContext) request.getContext()).getClientRequest().getHeaders().getFirst("X-Version");
    // 过滤Nacos中的元数据,匹配version的服务实例
}

重试配置

spring:
  cloud:
    loadbalancer:
      retry:
        enabled: true
        max-retries-on-same-service-instance: 2
        max-retries-on-next-service-instance: 3

注意:需要引入spring-retry依赖,且Feign重试需禁用全局重试以免冲突。


性能对比与最佳实践陷阱

维度 Ribbon Spring Cloud LoadBalancer
响应式 不支持 原生支持
平均响应时间(500并发) 45ms 38ms(因异步非阻塞)
内存占用 低(无Netflix组件)

坑点警示

  1. 缓存饥饿:默认缓存TTL为35s,会导致新上线的服务实例不可见。解决:设置spring.cloud.loadbalancer.cache.ttl=3s
  2. Nacos权重不生效:需要配置spring.cloud.loadbalancer.nacos.enabled=true
  3. 同集群优先调用:使用spring-cloud-starter-alibaba-nacos-discovery中的NacosServiceInstanceListSupplier,并开启spring.cloud.loadbalancer.nacos.cluster-name

常见问题Q&A(含故障排查)

Q1:Feign调用时报错Load balancer does not have available server for client: xxx → 检查Nacos中服务是否注册成功;确认消费者是否引入了loadbalancer依赖;查看Nacos集群命名空间是否一致。

Q2:为什么自定义权重不生效? → 确认服务提供者设置了spring.cloud.nacos.discovery.weight=2(范围0-100),且消费者明确指定spring.cloud.loadbalancer.nacos.weighted=true

Q3:如何强制走指定IP而不走负载均衡? → 使用@LoadBalancedRestTemplate无法绕过,可改用普通RestTemplate(不注入@LoadBalanced),直接URL写IP。

Q4:WS(WebSocket)长连接被负载均衡踢下线? → 需配合Spring Session或粘滞会话(Sticky Session),SCLB不内置粘滞功能,建议使用网关层一致性哈希。


通过上述案例可见,Spring Cloud LoadBalancer在功能上完全替代Ribbon,并在响应式、可扩展性上更胜一筹。关键跃迁思维:从“同步阻塞调用”转向“响应式声明式调用”,并在生产环境中精细化配置缓存与重试策略,建议团队在微服务迁移时,优先将Feign与WebClient结合SCLB,以最大化吞吐量。

抱歉,评论功能暂时关闭!