负载均衡

返回 Spring Cloud

Spring Cloud 采用客户端负载均衡:Consumer 从注册中心拉取实例列表后在本地选择目标实例,无需额外的 LB 服务器。Spring Boot 3.x / Spring Cloud 2022+ 默认使用 Spring Cloud LoadBalancer,已替代停维护的 Ribbon

Spring Cloud LoadBalancer

依赖

<!-- 已内嵌在 nacos/eureka starter 中,通常无需单独引入 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

@LoadBalanced RestTemplate

@Configuration
public class RestConfig {
    @Bean
    @LoadBalanced   // 拦截请求,将服务名解析为真实地址
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
 
@Service
public class OrderClient {
    @Autowired
    private RestTemplate restTemplate;
 
    public Order getOrder(Long id) {
        return restTemplate.getForObject(
            "http://order-service/orders/{id}", Order.class, id);
    }
}

@LoadBalanced WebClient

@Bean
@LoadBalanced
public WebClient.Builder webClientBuilder() {
    return WebClient.builder();
}
 
public Mono<Order> getOrder(Long id) {
    return webClientBuilder.build()
        .get()
        .uri("http://order-service/orders/{id}", id)
        .retrieve()
        .bodyToMono(Order.class);
}

内置策略

策略类名说明
轮询(默认)RoundRobinLoadBalancer依次轮流选择实例
随机RandomLoadBalancer随机选择实例

切换为随机策略

@Configuration
@LoadBalancerClient(name = "order-service",
                    configuration = RandomLBConfig.class)
public class LoadBalancerConfig {}
 
// 注意:此类不能加 @Configuration,避免被全局扫描
public class RandomLBConfig {
    @Bean
    public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(
            Environment env,
            LoadBalancerClientFactory factory) {
        String name = env.getProperty(
            LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(
            factory.getLazyProvider(name, ServiceInstanceListSupplier.class),
            name);
    }
}

自定义策略

public class WeightedLoadBalancer
    implements ReactorServiceInstanceLoadBalancer {
 
    private final ObjectProvider<ServiceInstanceListSupplier> provider;
    private final String serviceId;
 
    @Override
    public Mono<Response<ServiceInstance>> choose(Request request) {
        return provider
            .getIfAvailable(NoopServiceInstanceListSupplier::new)
            .get(request)
            .next()
            .map(instances -> {
                ServiceInstance chosen = weightedRandom(instances);
                return new DefaultResponse(chosen);
            });
    }
}

实例缓存配置

spring:
  cloud:
    loadbalancer:
      cache:
        enabled: true
        ttl: 35s        # 缓存 TTL,建议略大于注册中心推送延迟
        capacity: 256

Nacos 权重 + 集群优先路由

Nacos 的 NacosLoadBalancer 支持按实例权重加权随机,并优先选择与 Consumer 同集群的实例:

spring:
  cloud:
    nacos:
      discovery:
        cluster-name: SH    # Consumer 所在集群名

相关链接

Spring Cloud

架构