微服务之Spring Cloud LoadBalancer

张开发
2026/4/8 18:45:30 15 分钟阅读

分享文章

微服务之Spring Cloud LoadBalancer
Spring Cloud LoadBalancerSCLB核心知识梳理一、核心定位Spring 官方推出的 客户端负载均衡器自 Spring Cloud 2020.0.0 起替代 Netflix Ribbon 成为默认方案适配微服务架构轻量、响应式、持续维护。核心逻辑服务消费者本地缓存服务列表按策略选择实例直接调用无中间转发避免中心单点。二、核心优势对比 Ribbon官方原生Spring 团队维护持续更新无第三方依赖包袱响应式优先基于 Project Reactor原生支持 WebFlux、Spring Gateway轻量级仅保留核心LB能力启动快、占用资源少健康检查内置主动探测默认 /actuator/health自动剔除故障节点配置灵活支持全局/服务级配置与 Spring Boot 配置体系无缝融合三、核心架构与组件ReactiveLoadBalancer核心接口负责选择服务实例核心方法MonoResponse choose(Request)核心实现RoundRobinLoadBalancer默认、RandomLoadBalancerServiceInstanceListSupplier从注册中心Nacos/Eureka获取、过滤、缓存服务实例列表仅返回 UP 状态实例LoadBalancerClientFactory工厂类为每个服务创建独立的 LoadBalancer 实例LoadBalanced注解为 RestTemplate / WebClient 开启负载均衡拦截自动解析服务名四、工作流程4步拉取列表通过 DiscoveryClient 从注册中心拉取服务实例本地缓存默认35s过期健康过滤剔除 DOWN/不可用实例筛选出可用实例列表策略选择按配置的负载均衡策略选择一个目标实例请求转发将服务名替换为实例的 IP:Port发起直接调用五、内置负载均衡策略策略类核心说明适用场景RoundRobinLoadBalancer默认原子计数器轮询线程安全均匀分发实例性能相近、需均匀分配流量RandomLoadBalancer基于 ThreadLocalRandom 随机选择简单高效无状态服务、大流量场景追求简单均衡六、快速集成与使用Spring Boot Nacos依赖配置Mavenorg.springframework.cloud spring-cloud-starter-loadbalancer com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery配置类开启负载均衡方式1RestTemplate阻塞式适用于传统Spring MVCConfigurationpublic class RestTemplateConfig {BeanLoadBalanced // 关键开启负载均衡拦截public RestTemplate restTemplate() {return new RestTemplate();}}方式2WebClient响应式推荐适用于WebFluxConfigurationpublic class WebClientConfig {BeanLoadBalancedpublic WebClient.Builder webClientBuilder() {return WebClient.builder();}}服务调用用服务名替代IPRestTemplate 调用Servicepublic class OrderService {Autowiredprivate RestTemplate restTemplate;// 直接使用服务名user-serviceLB自动解析为IP:Port public String getUser(Long userId) { return restTemplate.getForObject(http://user-service/user/ userId, String.class); }}WebClient 响应式调用Servicepublic class ReactiveOrderService {Autowiredprivate WebClient.Builder webClientBuilder;public MonoString getUser(Long userId) { return webClientBuilder.build() .get() .uri(http://user-service/user/ userId) .retrieve() .bodyToMono(String.class); }}七、OpenFeign 与 SCLB 集成配置微服务调用专属微服务间基于 OpenFeign 调用时无需额外配置 SCLB 负载均衡核心逻辑Spring Cloud 2020.0.0 已默认集成 SCLB 替代 Ribbon但需完成 OpenFeign 基础配置 集成依赖确保负载均衡、重试、超时等功能正常生效。核心依赖配置Maven需同时引入 OpenFeign 和 SCLB 依赖Nacos 依赖中虽集成 SCLB但单独引入可避免调用异常无需额外引入 Ribbon 依赖避免冲突org.springframework.cloud spring-cloud-starter-openfeign org.springframework.cloud spring-cloud-starter-loadbalancer com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery org.springframework.retry spring-retry启动类开启 OpenFeign核心配置在服务消费者启动类上添加 EnableFeignClients 注解开启 OpenFeign 客户端功能自动扫描 Feign 接口SpringBootApplicationEnableFeignClients // 开启OpenFeign客户端EnableDiscoveryClient // 开启服务发现Nacos/Eurekapublic class ConsumerApplication {public static void main(String[] args) {SpringApplication.run(ConsumerApplication.class, args);}}定义 Feign 接口服务调用核心Feign 接口中通过 FeignClient(name “服务名”) 绑定目标服务接口方法与服务提供者保持一致SCLB 会自动对该接口的调用进行负载均衡// 绑定目标服务服务名与注册中心一致如user-serviceFeignClient(name “user-service”)public interface UserFeignClient {// 接口方法与服务提供者完全一致请求方式、路径、参数GetMapping(“/user/{id}”)String getUserById(PathVariable(“id”) Long id);PostMapping(/user/save) Boolean saveUser(RequestBody User user);}关键补充配置application.yml需配置 Feign 自身超时、日志以及 SCLB 负载均衡、重试策略与 SCLB 全局配置兼容确保调用稳定spring:cloud:# SCLB 配置与前文全局配置一致无需重复可补充Feign专属适配loadbalancer:retry:enabled: true # 开启重试配合Feign调用失败重试max-retries-on-same-service-instance: 0 # 同一实例不重试max-retries-on-next-service-instance: 1 # 切换实例重试1次nacos:enabled: true # 开启Nacos与SCLB适配Nacos注册中心必配nacos:discovery:server-addr: nacos-node1:8848,nacos-node2:8848 # 注册中心地址Feign 专属配置feign:client:config:default: # 全局配置所有Feign接口生效connectTimeout: 1000 # Feign连接超时需与SCLB超时匹配readTimeout: 2000 # Feign读取超时loggerLevel: basic # 日志级别basic仅记录请求/响应状态启用SCLB负载均衡默认已启用无需手动开启防止误配Ribbonloadbalancer:enabled: true配合重试启用Spring Retry需引入spring-retry依赖retry:enabled: true特殊场景配置指定服务负载均衡策略若某一Feign接口如pay-service需单独配置SCLB策略可沿用SCLB服务级配置Feign会自动继承该策略。Feign 日志精细化如需调试可将 loggerLevel 设为 full同时配置对应Feign接口的日志级别为DEBUG。避免 Ribbon 冲突若项目中存在Ribbon依赖需排除Ribbon确保SCLB生效OpenFeign默认优先使用SCLB。响应式 Feign若使用 WebFlux可引入 spring-cloud-starter-openfeign-reactive 依赖适配SCLB响应式负载均衡。补充说明OpenFeign 会自动集成 SCLB无需在 Feign 接口或配置类中添加 LoadBalanced 注解仅需保证 SCLB 依赖存在且配置正确即可底层由 FeignBlockingLoadBalancerClient 实现负载均衡调用。八、核心配置application.yml全局配置spring:cloud:loadbalancer:# 缓存配置默认开启提升性能cache:enabled: truettl: 35s # 缓存过期时间默认35scapacity: 256 # 最大缓存实例数# 健康检查配置health-check:path:default: /actuator/health # 默认健康检查路径interval: 10s # 健康检查间隔# 超时配置client:connect-timeout: 1000 # 连接超时msread-timeout: 2000 # 读取超时ms# 重试配置retry:enabled: true # 开启重试max-retries-on-same-service-instance: 0 # 同一实例不重试max-retries-on-next-service-instance: 1 # 切换实例重试1次# 饥饿加载解决首次调用慢eager-load:enabled: trueclients: user-service,order-service # 预加载的服务名服务级配置指定单个服务策略// 全局配置类指定user-service使用轮询策略ConfigurationLoadBalancerClient(name “user-service”, configuration UserServiceLBConfig.class)public class GlobalLBConfig {}// 单个服务的负载均衡策略配置class UserServiceLBConfig {Beanpublic ReactorLoadBalancer roundRobinLoadBalancer(Environment env, LoadBalancerClientFactory factory) {String serviceId env.getProperty(“loadbalancer.client.name”);return new RoundRobinLoadBalancer(factory.getLazyProvider(serviceId, ServiceInstance.class), serviceId);}}九、自定义负载均衡策略加权轮询示例// 1. 自定义加权轮询策略public class WeightedLoadBalancer implements ReactiveLoadBalancer {private final String serviceId;private final SupplierMonoList instanceSupplier;// 构造方法注入实例供应器和服务ID public WeightedLoadBalancer(SupplierMonoListServiceInstance supplier, String serviceId) { this.serviceId serviceId; this.instanceSupplier supplier; } Override public MonoResponseServiceInstance choose(Request request) { return instanceSupplier.get() .map(instances - { if (instances.isEmpty()) { return new EmptyResponse(); // 无可用实例 } // 核心根据实例元数据中的weight属性选择 return new DefaultResponse(selectByWeight(instances)); }); } // 加权选择逻辑遍历实例根据权重分配 private ServiceInstance selectByWeight(ListServiceInstance instances) { int totalWeight instances.stream() .mapToInt(instance - Integer.parseInt(instance.getMetadata().getOrDefault(weight, 1))) .sum(); int randomWeight new Random().nextInt(totalWeight) 1; int currentWeight 0; for (ServiceInstance instance : instances) { currentWeight Integer.parseInt(instance.getMetadata().getOrDefault(weight, 1)); if (currentWeight randomWeight) { return instance; } } return instances.get(0); // 兜底返回第一个实例 }}// 2. 注册自定义策略指定pay-service使用加权策略ConfigurationLoadBalancerClient(name “pay-service”, configuration WeightedLBConfig.class)public class CustomLBConfig {}class WeightedLBConfig {Beanpublic ReactorLoadBalancer weightedLoadBalancer(Environment env, LoadBalancerClientFactory factory) {String serviceId env.getProperty(“loadbalancer.client.name”);return new WeightedLoadBalancer(factory.getLazyProvider(serviceId, ServiceInstance.class), serviceId);}}十、生产最佳实践策略选型通用场景RoundRobinLoadBalancer默认均匀分发异构实例性能差异大自定义加权策略无状态、大流量RandomLoadBalancer性能优化开启缓存、饥饿加载减少注册中心拉取频率高可用保障启用健康检查、重试机制自动剔除故障节点超时控制合理配置连接/读取超时避免长时间阻塞服务隔离为不同服务配置独立策略避免相互影响OpenFeign 适配Feign超时与SCLB超时保持一致开启重试时需引入spring-retry依赖避免重复配置冲突。十一、面试高频考点Spring Cloud LoadBalancer 与 Ribbon 的核心区别LoadBalancerSpring 官方、响应式、轻量、持续维护支持 WebFluxRibbonNetflix 开源、阻塞式、已停更、依赖重不支持响应式SCLB 的默认负载均衡策略是什么RoundRobinLoadBalancer轮询SCLB 如何实现健康检查定期调用实例的 /actuator/health 接口标记 DOWN 实例并剔除LoadBalanced 注解的作用拦截 RestTemplate/WebClient 的请求将服务名解析为具体的 IP:Port如何解决 SCLB 首次调用慢的问题开启饥饿加载eager-load预加载指定服务的实例列表OpenFeign 与 SCLB 集成需要单独配置负载均衡吗无需单独配置引入依赖并开启EnableFeignClientsFeign会自动集成SCLB实现负载均衡。十二、总结Spring Cloud LoadBalancer 是 现代微服务客户端负载均衡的首选方案轻量、可靠、响应式、易扩展完美替代停更的 Ribbon。新项目必用老项目建议逐步迁移适配 Spring Cloud 新版本生态。微服务间基于 OpenFeign 调用时核心是完成 Feign 基础配置与依赖引入SCLB 会自动适配无需额外配置负载均衡核心逻辑配合合理的超时、重试配置即可实现稳定的服务调用。

更多文章