SpringCloud LoadBalancer‌负载均衡 在微服务架构中客户端负载均衡是保障服务高可用与高性能的关键组件。Spring Cloud LoadBalancer 作为 Spring Cloud 官方推出的新一代负载均衡器不仅提供了轻量级的内置策略还支持灵活的自定义扩展完美适配现代响应式编程模型。本文将深入解析其核心原理、与 Ribbon 的主要区别并通过从基础使用到自定义策略的完整示例帮助您快速掌握这一重要工具为构建健壮的微服务系统打下坚实基础。一Spring Cloud LoadBalancer‌原理Spring Cloud LoadBalancer是Spring Cloud官方推出的‌客户端负载均衡组件‌核心工作原理如下核心执行流程客户端从Nacos/Eureka等注册中心拉取可用服务实例列表缓存到本地。通过LoadBalancerClientFactory获取对应服务的负载均衡器实例。调用内置的choose()方法基于轮询/随机等预设策略从实例列表中选中一个目标服务节点。重构请求URL直接向选中的实例发起远程调用。核心内置实现它提供了两个默认负载均衡器RoundRobinLoadBalancer轮询策略按顺序依次分发请求是默认策略。RandomLoadBalancer随机策略随机从可用实例中挑选节点。同时支持通过实现ReactorServiceInstanceLoadBalancer接口快速自定义负载均衡策略。3. 关键特性它同时支持阻塞式和响应式编程模型适配RestTemplate、Feign、WebClient等多种调用方式完全替代已停更的Ribbon组件适配新版Spring Cloud全生态。二Spring Cloud LoadBalancer和Ribbon的核心区别如下一、基础定位与维护状态‌Ribbon‌Netflix开源的老牌负载均衡组件目前已‌停止官方维护‌仅适配Spring Cloud早期版本。‌Spring Cloud LoadBalancer‌Spring Cloud官方自研的新一代负载均衡组件是官方指定的Ribbon替代方案持续迭代更新适配所有新版本Spring Cloud。二、核心特性差异‌编程模型‌Ribbon仅支持传统阻塞式编程LoadBalancer同时支持阻塞式和响应式编程适配WebFlux等现代技术栈。‌内置策略‌Ribbon提供7种以上内置负载均衡策略LoadBalancer默认仅内置轮询、随机两种基础策略更轻量化支持快速自定义扩展。‌生态兼容性‌Ribbon和Eureka、Hystrix等旧版Netflix生态深度绑定LoadBalancer原生适配Nacos、Spring Cloud Gateway等新一代Spring Cloud生态组件。三、适用场景‌Ribbon‌仅适合维护老旧Spring Cloud项目不建议新项目使用。‌Spring Cloud LoadBalancer‌所有新开发的微服务项目的首选方案性能更优、扩展性更强长期维护性更好。三、简单示例下面是一个使用 Spring Cloud LoadBalancer 配合WebClient进行服务调用的简单示例。1. 添加依赖在pom.xml中添加必要的依赖dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-loadbalancer/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-webflux/artifactId/dependency2. 配置启用负载均衡确保您的应用已连接到服务注册中心如 Nacos、Eureka。3. 创建负载均衡的 WebClient使用LoadBalanced注解创建一个具备负载均衡能力的WebClient.BuilderBean。importorg.springframework.cloud.client.loadbalancer.LoadBalanced;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.reactive.function.client.WebClient;ConfigurationpublicclassWebClientConfig{BeanLoadBalancedpublicWebClient.BuilderloadBalancedWebClientBuilder(){returnWebClient.builder();}}4. 使用 WebClient 调用服务在您的服务类中注入WebClient.Builder并使用服务名而非具体IP和端口发起请求。importorg.springframework.stereotype.Service;importorg.springframework.web.reactive.function.client.WebClient;importreactor.core.publisher.Mono;ServicepublicclassUserService{privatefinalWebClientwebClient;publicUserService(WebClient.BuilderwebClientBuilder){// 使用服务名 user-service 构建 WebClientthis.webClientwebClientBuilder.baseUrl(http://user-service).build();}publicMonoStringgetUserInfo(LonguserId){returnthis.webClient.get().uri(/users/{id},userId).retrieve().bodyToMono(String.class);}}示例说明当调用getUserInfo方法时WebClient会通过 Spring Cloud LoadBalancer 将请求http://user-service/users/{id}负载均衡到名为user-service的某个健康实例上。LoadBalancer 会自动从注册中心获取user-service的实例列表并依据默认的轮询策略选择一个实例。通过以上几步您就完成了一个简单的、具备客户端负载均衡能力的服务调用。4. 自定义负载均衡策略示例Spring Cloud LoadBalancer 支持通过实现ReactorServiceInstanceLoadBalancer接口来自定义负载均衡策略。下面展示一个简单的基于权重的选择策略示例假设每个服务实例有一个权重属性权重越高的实例被选中的概率越大。4.1 实现自定义负载均衡器创建一个实现ReactorServiceInstanceLoadBalancer接口的类importorg.springframework.cloud.client.ServiceInstance;importorg.springframework.cloud.client.loadbalancer.DefaultResponse;importorg.springframework.cloud.client.loadbalancer.EmptyResponse;importorg.springframework.cloud.client.loadbalancer.Request;importorg.springframework.cloud.client.loadbalancer.Response;importorg.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;importreactor.core.publisher.Mono;importjava.util.List;importjava.util.concurrent.ThreadLocalRandom;publicclassWeightedLoadBalancerimplementsReactorServiceInstanceLoadBalancer{privatefinalStringserviceId;privatefinalListServiceInstanceserviceInstances;publicWeightedLoadBalancer(StringserviceId,ListServiceInstanceserviceInstances){this.serviceIdserviceId;this.serviceInstancesserviceInstances;}OverridepublicMonoResponseServiceInstancechoose(Requestrequest){if(serviceInstances.isEmpty()){returnMono.just(newEmptyResponse());}// 计算总权重inttotalWeightserviceInstances.stream().mapToInt(instance-getWeight(instance)).sum();if(totalWeight0){// 如果所有实例权重都0则随机选择一个intrandomIndexThreadLocalRandom.current().nextInt(serviceInstances.size());returnMono.just(newDefaultResponse(serviceInstances.get(randomIndex)));}// 生成一个 [0, totalWeight) 的随机数intrandomWeightThreadLocalRandom.current().nextInt(totalWeight);intcurrentWeight0;// 按权重区间选择实例for(ServiceInstanceinstance:serviceInstances){currentWeightgetWeight(instance);if(randomWeightcurrentWeight){returnMono.just(newDefaultResponse(instance));}}// 兜底返回第一个实例returnMono.just(newDefaultResponse(serviceInstances.get(0)));}/** * 从实例的元数据metadata中获取权重值默认权重为1 */privateintgetWeight(ServiceInstanceinstance){StringweightStrinstance.getMetadata().get(weight);if(weightStr!null){try{returnInteger.parseInt(weightStr);}catch(NumberFormatExceptione){// 解析失败则返回默认权重}}return1;// 默认权重}}4.2 配置自定义负载均衡器创建一个配置类将自定义的负载均衡器注册到 Spring 容器中importorg.springframework.cloud.client.ServiceInstance;importorg.springframework.cloud.client.discovery.DiscoveryClient;importorg.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.context.annotation.Primary;importjava.util.List;ConfigurationpublicclassLoadBalancerConfiguration{BeanPrimarypublicReactorServiceInstanceLoadBalancercustomLoadBalancer(DiscoveryClientdiscoveryClient,ServiceInstanceListSuppliersupplier){returnserviceInstanceList-supplier.get().next().map(instances-{// 这里可以针对特定服务进行配置StringserviceIduser-service;// 替换为你的服务名ListServiceInstanceserviceInstancesdiscoveryClient.getInstances(serviceId);returnnewWeightedLoadBalancer(serviceId,serviceInstances);});}}4.3 为服务实例配置权重在服务实例的注册信息中添加权重元数据。以 Nacos 为例在服务的bootstrap.yml或application.yml中配置spring:cloud:nacos:discovery:metadata:weight:3# 权重值数字越大被选中的概率越高4.4 使用自定义策略应用启动后所有对user-service的负载均衡请求都会使用我们实现的权重策略。你无需修改之前的WebClient调用代码LoadBalancer 会自动使用注册的自定义负载均衡器。实现原理说明WeightedLoadBalancer从服务实例的元数据中读取weight字段作为权重值。选择时根据所有权重值总和生成随机数落在哪个实例的权重区间就选择哪个实例。权重越高区间范围越大被选中的概率就越高。通过LoadBalancerConfiguration将自定义负载均衡器注册为特定服务的默认实现。通过这个示例你可以看到 Spring Cloud LoadBalancer 的自定义扩展非常灵活只需实现一个接口即可定义复杂的负载均衡逻辑。