springcloud LoadBalancerClient 负载策略原理

springcloud LoadBalancerClient 负载策略原理

springcloud 提供了跟多组件以及大量与服务治理相关的抽象接口,LoadBalancerClient为springcloud提供的负载均衡器客户端。

LoadBalancerClient先从提供的服务中获取某一个实例(默认策略为轮询),比如订单服务需要访问商品服务,商品服务有3个节点,LoadBalancerClient会通过choose(),方法获取到3个节点中的一个服务,拿到服务的信息之后取出服务ip信息,就可以得到完成的想要访问的ip地址和接口,最后通过RestTempate访问商品服务。

springcloud提供的组件Ribbon,内部就是集成了LoadBalancerClient负载均衡,通过@LoadBalance注解开启负载均衡器。

深入解析LoadBalancerClient接口源码

首页我们开始追踪LoadBalancerClient源码,
在这里插入图片描述
可以发现LoadBalancerClient接口继承了ServiceInstanceChooser接口,主要的方法为2个execute方法,均是用来执行请求的。还有个reconstructURI()是用来重构URL的。

进入ServiceInstanceChooser接口内容看下:
在这里插入图片描述
进入ServiceInstanceChooser接口中,可以看到主要的方法为choose(),这是是用来根据服务的名称,获取来选择其中一个服务实例。也就是根据seriverid获取ServiceInstance。

在看看LoadBalancerClient的实现类RibbonLoadBalancerClient。
在这里插入图片描述
综上我们可以知道LoadBalancerClient接口一个结构情况了:
在这里插入图片描述
现在我们在进入到LoadBalancerClient的实现类RibbonLoadBalancerClient里面看下,RibbonLoadBalancerClient实现类是非常重要的类。他就是实现了服务的负载和选择,以及负载策略的配置,整个的负载均衡都由它实现。

我们看下RibbonLoadBalancerClient实现类里面几个重要的实现方法:
第一个:choose(),用来选择具体的服务实例。
在这里插入图片描述
第二个:getServer(),获取实例。
在这里插入图片描述
最终通过ILoadBalancer去做服务选择实例。

我们放一起来看下:
在这里插入图片描述
那现在我们在看下ILoadBalancer是怎么实现选择服务实例的:
我们从上面也能看到ILoadBalancer中的chooseServer方法里面默认值为:default。
进入ILoadBalancer 实现类BaseLoadBalancer看下:
跟着刚才的chooseServer()方法进去:
在这里插入图片描述
我们的key为“default”,那么我们去看下这个key代表的是什么意思吧。进去rule对象里面看下:
在这里插入图片描述
我们可以看到这个rule是IRule接口声明出来的,且默认定义的实现类是RoundRobinRule(),也就是轮询策略。
那我们看下IRule接口:
在这里插入图片描述我们可以看到IRule接口定义了3个方法,choose是用来选择实例的,setLoadBalancer和getLoadBalance用来设置和获取ILoadBalancer的。
那我们来看下IRule接口有多少个实现类吧:
在这里插入图片描述
可以看到IRule里面有很多策略实现类。这样我们是不是就可以通过IRule接口实现一个自定义负载策略了呢,来看下:
在这里插入图片描述
的确是这样的,IRule定义了一个方法,这里返回了RandomRule实现类,也就是随机策略。

总结

以上源码内容比较多,一定要细心研究,我们来总结下流程:

1.LoadBalancerClient——>RibbonLoadBalancerClient中的choose()

首先我们穿一个serverid,也就是服务id,通过LoadBalancerClient接口调用实现类RibbonLoadBalancerClient中的**choose(serverid)**方法。
在这里插入图片描述

2.choose()---->getServer(ILoadBalancer loadbalance)----->chooseServer()
choose(serverid)内部调用getServer(ILoadBalancer loadBalancer, Object hint),getServer方法通过ILoadBalancer类进行了负载策均衡之旅。
在这里插入图片描述
3.实现chooseServer()方法
接着通过实现ILoaddBalancer接口的chooseServer(Object key)方法,实现类为BaseLoadBalancer。
在这里插入图片描述
4. 通过IRule接口,自定义负载策略。

其实LoadBalancerClient 还有个核心类IPing,这里就不多解析了,向EurekaClient获取注册列表信息,默认每10秒向EurekaClient发送一次“ping”,进而检查是否需要更新服务的注册列表信息。

负载均衡的实现LoadBalancerClient具体交给了ILoadBalancer来处理,ILoadBalancer通过配置IRule、IPing等,向EurekaClient获取注册列表信息,默认每10秒向EurekaClient发送一次“ping”,进而检查是否需要更新服务的注册列表信息。最后,在得到服务注册列表信息后,ILoadBalancer根据IRule的策略进行负载均衡。

<think>我们正在使用SpringCloud LoadBalancer作为负载均衡器,并且希望自定义负载均衡策略。根据引用[2],Spring CloudBalancer默认提供了轮询和随机两种策略。现在我们需要替换为自定义策略。步骤:1.创建自定义的负载均衡策略类,实现ReactorLoadBalancer接口(或使用SpringCloud LoadBalancer的API)。2.配置自定义的负载均衡策略,使其被Spring容器管理。3.通过配置指定使用自定义的负载均衡策略。具体实现如下:第一步:创建自定义负载均衡策略我们可以参考Spring CloudLoadBalancer中已有的实现(如RoundRobinLoadBalancer)来创建自己的策略。例如,我们创建一个简单的自定义负载均衡策略(假设我们实现一个总是选择第一个实例的策略,仅用于演示):```javaimportorg.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.loadbalancer.Request;import org.springframework.cloud.client.loadbalancer.Response;import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer; importreactor.core.publisher.Mono; importjava.util.List;public classFirstInstanceLoadBalancer implementsReactorServiceInstanceLoadBalancer {privatefinal StringserviceId;privatefinal List<ServiceInstance>instances; //注意:实际中我们不会这样写,这里仅作示例//实际中,我们可能会使用一个ServiceInstanceSupplier来获取实例列表,这里简化publicFirstInstanceLoadBalancer(StringserviceId, List<ServiceInstance>instances){this.serviceId =serviceId;this.instances= instances;}@Overridepublic Mono<Response<ServiceInstance>>choose(Requestrequest){//总是返回第一个实例if (instances.isEmpty()){return Mono.empty();}returnMono.just(newResponse<ServiceInstance>() {@OverridepublicServiceInstancegetServer() {returninstances.get(0);}@Overridepublicboolean hasServer(){return true;}});} }```但是,上面的例子过于简单,实际中我们需要从服务发现中动态获取实例列表。因此,我们可以参考SpringCloud LoadBalancer的默认实现,使用一个ServiceInstanceListSupplier来获取实例列表。更合理的自定义负载均衡器实现(使用ServiceInstanceListSupplier): ```javaimport org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.loadbalancer.Request;import org.springframework.cloud.client.loadbalancer.Response;import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer; importorg.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; importreactor.core.publisher.Mono; importjava.util.List;public classCustomLoadBalancerimplements ReactorServiceInstanceLoadBalancer{private finalServiceInstanceListSupplierserviceInstanceListSupplier;private finalString serviceId;publicCustomLoadBalancer(ServiceInstanceListSupplier serviceInstanceListSupplier,String serviceId){this.serviceInstanceListSupplier =serviceInstanceListSupplier;this.serviceId =serviceId;}@Overridepublic Mono<Response<ServiceInstance>>choose(Requestrequest){//获取可用的服务实例列表return serviceInstanceListSupplier.get().next().map(instances-> {//自定义选择逻辑:这里我们选择第一个实例if(instances.isEmpty()) {returnnull;}returnnew Response<ServiceInstance>(){@Overridepublic ServiceInstance getServer(){return instances.get(0);}@Overridepublicboolean hasServer(){return true;}};});} }```第二步:创建配置类,定义我们的自定义负载均衡器我们需要为每个服务创建一个负载均衡器实例。可以通过配置类来创建。 ```javaimport org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; importorg.springframework.context.ConfigurableApplicationContext;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration; @Configurationpublic classCustomLoadBalancerConfiguration {@BeanpublicReactorLoadBalancer<ServiceInstance>customLoadBalancer(ConfigurableApplicationContext context,ServiceInstanceListSuppliersupplier){//这里我们使用服务名(可以通过配置获取,但这里为了简化,我们假设服务名是已知的,实际中可能需要动态获取)//注意:在实际中,我们可能需要为不同的服务配置不同的负载均衡器,这里我们使用同一个自定义类//但是,Spring CloudLoadBalancer允许我们为不同的服务配置不同的负载均衡配置类(通过@LoadBalancerClient注解指定)String serviceId= supplier.getServiceId();returnnew CustomLoadBalancer(supplier, serviceId);}} ```第三步:通过@LoadBalancerClient注解指定使用自定义负载均衡配置在启动类上或者配置类上,使用@LoadBalancerClient注解,指定哪个服务使用我们的自定义负载均衡配置。 ```javaimport org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient; importorg.springframework.context.annotation.Configuration; @Configuration@LoadBalancerClient(name= "your-service-name", configuration= CustomLoadBalancerConfiguration.class)public classMyLoadBalancerConfig{ }```注意:将"your-service-name"替换为你要应用自定义负载均衡策略的服务名。另外,也可以使用@LoadBalancerClients注解配置多个服务。这样,当通过OpenFeign调用"your-service-name"服务时,就会使用我们自定义的负载均衡策略。补充说明:在Spring CloudLoadBalancer中,我们还可以通过配置属性来切换默认的负载均衡策略(如轮询或随机),但自定义策略需要按照上述方式实现。参考引用[2]中提到的负载均衡器接口和已有实现,我们可以扩展自己的策略。注意:自定义负载均衡策略时,需要确保正确处理服务实例列表的获取和选择逻辑,并注意异常处理。以上就是在OpenFeign集成Spring CloudLoadBalancer时实现并替换为自定义负载均衡策略的方法。相关问题:1.如何为不同的微服务配置不同的负载均衡策略?2.Spring CloudLoadBalancer中如何实现健康检查过滤实例?3.自定义负载均衡策略时,如何获取请求的上下文信息(如请求头)来辅助决策?</think>### 在 OpenFeign 中集成自定义负载均衡策略 在 OpenFeign 集成 Spring Cloud LoadBalancer 时替换默认负载均衡算法,需通过以下步骤实现自定义策略: #### 1. **创建自定义负载均衡策略** 实现 `ReactorLoadBalancer` 接口,重写实例选择逻辑: ```java import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer; import reactor.core.publisher.Mono; public class CustomLoadBalancer implements ReactorServiceInstanceLoadBalancer { private final String serviceId; private final List<ServiceInstance> instances; public CustomLoadBalancer(String serviceId, List<ServiceInstance> instances) { this.serviceId = serviceId; this.instances = instances; } @Override public Mono<Response<ServiceInstance>> choose(Request request) { // 自定义选择逻辑(示例:权重优先算法) ServiceInstance selected = selectByWeight(instances); return Mono.just(new DefaultResponse(selected)); } private ServiceInstance selectByWeight(List<ServiceInstance> instances) { // 实现自定义权重算法 // 例如:根据实例元数据中的权重值选择 return instances.get(0); // 简化示例 } } ``` #### 2. **配置自定义负载均衡器** 通过配置类注册自定义策略: ```java import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @LoadBalancerClient( name = "your-service", // 目标微服务名称 configuration = CustomLoadBalancerConfig.class ) public class CustomLoadBalancerConfig { @Bean public ReactorLoadBalancer<ServiceInstance> customLB( Environment environment, LoadBalancerClientFactory factory ) { String serviceId = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); return new CustomLoadBalancer(serviceId, factory.getInstances(serviceId)); } } ``` #### 3. **禁用默认策略** 在 `application.yml` 中关闭默认负载均衡器: ```yaml spring: cloud: loadbalancer: ribbon: enabled: false # 禁用Ribbon(如果存在) configurations: custom # 使用自定义配置 ``` #### 关键原理说明 1. **动态代理机制** OpenFeign 通过动态代理生成客户端,`@FeignClient` 注解的接口会被拦截,实际调用由 `LoadBalancerFeignClient` 处理[^1]。 2. **负载均衡器选择** Spring Cloud LoadBalancer 通过 `ReactorLoadBalancer` 接口实现实例选择,默认提供轮询(`RoundRobinLoadBalancer`)和随机(`RandomLoadBalancer`)策略[^2]。 3. **配置生效流程** `@LoadBalancerClient` 注解优先于默认配置,Spring 容器会按名称将自定义策略注入到目标服务的调用链路中[^4]。 #### 验证自定义策略 在 Feign 客户端调用时添加日志: ```java @FeignClient(name = "your-service") public interface YourServiceClient { @GetMapping("/endpoint") String getData(); } ``` 观察控制台输出,确认请求是否按自定义逻辑路由到目标实例。 --- ### 相关问题 1. **如何为不同微服务配置不同的负载均衡策略?** 通过多个 `@LoadBalancerClient` 注解或 `@LoadBalancerClients` 注解,为每个服务指定独立的配置类。 2. **自定义策略如何实现健康检查过滤?** 在 `choose()` 方法中集成 `HealthCheckServiceInstanceListSupplier`,过滤掉不健康的实例[^2]。 3. **如何基于请求参数动态选择实例?** 通过 `Request` 对象获取请求上下文(如 Header 参数),在 `choose()` 方法中实现动态路由逻辑。 4. **自定义策略如何与 OpenFeign 重试机制协同工作?** 需配置 `Retryer` Bean 并设置重试次数,负载均衡失败时会触发重试[^3]。 5. **如何监控自定义策略的性能?** 集成 Micrometer 指标,在 `choose()` 方法中记录决策延迟和命中率。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Survivor001

你可以相信我,如果你愿意的话

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值