ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Spring Cloud LoadBalancer 详解

Spring Cloud LoadBalancer 详解 Spring Cloud LoadBalancer 是 Spring Cloud 官方提供的客户端负载均衡组件用来替代已经进入维护模式的 Ribbon。核心作用服务调用时在客户端本地选择一个服务实例再发起请求不是网关代理模式。一、基础概念1. 什么是客户端负载均衡客户端负载均衡调用方本地保存服务实例列表自己做算法选实例直接调用目标服务。对比 Nginx服务端负载均衡请求先到 Nginx由 Nginx 转发给后端服务。流程从注册中心 (Nacos/Eureka/Consul) 获取服务的全部实例列表LoadBalancer 在本地按照负载均衡算法挑选一个实例拼接服务实例地址发起 HTTP 请求Ribbon 已经停止维护Spring Cloud 2020.0 版本之后默认使用spring-cloud-loadbalancer。2. 核心依赖!-- spring cloud loadbalancer -- dependency groupIdorg.springframework.cloud/groupId artifactIdspring-cloud-starter-loadbalancer/artifactId /dependency如果使用OpenFeign/WebClient新版 Spring Cloud 不再自动引入负载均衡必须手动引入该依赖否则无法解析服务名。二、核心组件表格组件作用ServiceInstanceListSupplier获取服务实例列表从注册中心拉取支持缓存、过滤LoadBalancer顶层接口核心方法reconstructURI根据服务名选实例重构 URIReactorLoadBalancer响应式负载均衡实现Reactor 版本WebClientBlockingLoadBalancerClient阻塞式实现用于 RestTemplateLoadBalancerClient老接口兼容模式底层委托给 LoadBalancerLoadBalancerProperties配置属性类ReactorServiceInstanceLoadBalancer响应式负载均衡器内置负载均衡算法核心接口LoadBalancerpublic interface LoadBalancerT { MonoResponseT choose(Request request); }choose()传入服务名返回选中的服务实例ServiceInstance。三、内置负载均衡策略Spring Cloud LoadBalancer 内置两种策略1. Round‑Robin 轮询默认RoundRobinLoadBalancer按顺序轮流调用每个服务实例依次循环。无权重所有实例同等对待。2. Random 随机RandomLoadBalancer随机从实例列表挑选实例。⚠️注意原生内置不支持权重、最小连接数、一致性哈希如果需要权重、灰度、自定义规则需要自定义实现 ReactorServiceInstanceLoadBalancer。切换负载均衡策略方式为指定服务创建配置类注意不要被 ComponentScan 扫到全局生效。// 针对某个服务单独配置负载均衡策略 public class CustomLoadBalancerConfig { Bean public ReactorLoadBalancerServiceInstance reactorServiceInstanceLoadBalancer(Environment environment, LoadBalancerClientFactory factory){ String serviceName environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); return new RandomLoadBalancer(factory.getLazyProvider(serviceName, ServiceInstanceListSupplier.class),serviceName); } }使用注解指定服务LoadBalancerClient(value user-service, configuration CustomLoadBalancerConfig.class) SpringBootApplication public class App {}四、两种使用方式方式 1RestTemplate阻塞给 RestTemplate 添加LoadBalancedBean LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }调用直接写服务名不用写 ip 端口String url http://user-service/user/get; String resp restTemplate.getForObject(url,String.class);LoadBalanced底层原理给 RestTemplate 增加拦截器LoadBalancerInterceptor拦截 http 请求把服务名替换成真实 ip:port。方式 2WebClient响应式推荐Bean LoadBalanced public WebClient.Builder webClientBuilder(){ return WebClient.builder(); }webClientBuilder.build().get() .uri(http://user-service/user/get) .retrieve() .bodyToMono(String.class);底层LoadBalancerExchangeFilterFunction过滤器实现负载均衡。方式 3 OpenFeignOpenFeign 底层会自动适配 LoadBalancer只要引入 loadbalancer 依赖即可不需要额外注解。五、配置项 application.ymlspring: cloud: loadbalancer: # 是否开启缓存实例列表默认true减少注册中心请求 cache: enabled: true # 缓存过期时间 ttl: 30s # 重试配置 retry: enabled: true max-retries-on-same-service-instance: 1 # 同一个实例重试次数 max-retries-on-next-service-instance: 2 # 切换其他实例重试次数 # 健康检查定期ping实例剔除不健康实例 health-check: enabled: false实例缓存ServiceInstanceListSupplier默认会缓存实例列表不会每次调用都去注册中心拉取缓存 ttl 控制刷新频率。六、重试机制LoadBalancer 自带重试需要开启 spring.cloud.loadbalancer.retry.enabledtrue注意只会对 GET 等幂等请求重试POST 默认不会重试需要手动配置。重试逻辑请求失败先尝试重试当前实例 N 次当前实例全部失败切换其他实例重试 M 次坑开启重试要警惕接口非幂等造成重复提交。七、自定义负载均衡策略权重示例思路继承ReactorServiceInstanceLoadBalancer重写choose()方法获取全部可用ServiceInstance读取实例 metadata 中配置的权重instance.getMetadata().get(weight)根据权重算法选出实例返回注册为 Bean绑定指定服务名Nacos 可以在 metadata 里配置 weight 元数据LoadBalancer 原生不读取需要自己扩展。八、调用完整流程RestTemplate 发起请求http://user-service/xxxLoadBalancerInterceptor 拦截请求提取服务名user‑serviceServiceInstanceListSupplier从注册中心获取全部实例列表读本地缓存LoadBalancer 调用 choose ()轮询 / 随机选出一个 ServiceInstance将 URI 从http://user-service/xxx替换为http://127.0.0.1:8081/xxxS发起真实 http 调用失败时如果开启重试重复上述流程选其他实例。
返回列表