OpenFeign远程调用负载均衡原理详解

      SpringCloudAlibaba中使用OpenFeign时,默认的负载均衡策略是轮询调用。我们不做任何配置的时候,使用OpenFeign调用的时候,框架中是如何把负载均衡LoadBalanced和FeignClient结合到一起的?我们一起来分析一下。

1 DefaultFeignLoadBalancedConfiguration

位置:org.springframework.cloud.openfeign.ribbon.DefaultFeignLoadBalancedConfiguration

OpenFeign远程调用负载均衡原理详解_第1张图片 图1.1

项目启动的时候,会用LoadBalancerFeignClient注册一个feign.Client到ioc容器中。

FeignClientFactoryBean会生成一个@FeignClient注解的对应的service实例。

2 FeignClientFactoryBean

位置:org.springframework.cloud.openfeign.FeignClientFactoryBean

OpenFeign远程调用负载均衡原理详解_第2张图片 图2.1
OpenFeign远程调用负载均衡原理详解_第3张图片 图2.2

FeignClientFactoryBean实现了FactoryBean,我们都知道,在spring中实现了FactoryBean的类在spring生命周期过程中,spring会把 getObject() 返回的实例注册到ioc容器。方便以后实例的调用。

在spring生命周期过程中会调用getObject(),从ioc容器中获取到的client就是第一步注册到ioc容器的负载均衡实例LoadBalancerFeignClient,通过builder.client(client)到Feign.builder中。如图2.2。

OpenFeign远程调用负载均衡原理详解_第4张图片 图2.3
OpenFeign远程调用负载均衡原理详解_第5张图片 图2.4

现在我们可以分析图2.2最后一行。return targeter.target(this, builder, context, target)。以下图2.5和图2.6为FeignClientFactoryBean的getObject最终要初始化的实例。可以明显的看到创建了一个关于SynchronousMethodHandler.Factory的实例。第一个client参数就是上面已经注册好的LoadBalancerFeignClient的实例。

OpenFeign远程调用负载均衡原理详解_第6张图片 图2.5 OpenFeign远程调用负载均衡原理详解_第7张图片 图2.6

SynchronousMethodHandler 是个拦截器。项目初始话过程中,会为所有加了@FeignClient的service接口结合FeignClientFactoryBean生成对应接口的代理对象,客户端调用接口时会调用SynchronousMethodHandler的invoke方法。

OpenFeign远程调用负载均衡原理详解_第8张图片 图2.7
OpenFeign远程调用负载均衡原理详解_第9张图片 图2.8

 从图2.9可以看出调用servcie接口时是通过 client.execute(request, options) 调用的。client即为上面已经注册好的LoadBalancerFeignClient的实例。

OpenFeign远程调用负载均衡原理详解_第10张图片 图2.9

 3 探究client调用时如何做负载的?默认调用的哪种策略的负载?

跟进executeWithLoadBalancer方法。

OpenFeign远程调用负载均衡原理详解_第11张图片 图3.1

跟进submit方法

OpenFeign远程调用负载均衡原理详解_第12张图片 图3.2

可以看到图3.3中server为null的时候,执行selectServer()方法。跟进selectServer()。

OpenFeign远程调用负载均衡原理详解_第13张图片 图3.3

跟进getServerFromLoadBalancer()。

OpenFeign远程调用负载均衡原理详解_第14张图片 图3.4

继续跟进,可以看到 ILoadBalancer lb = getLoadBalancer(),可以获取到要负载的对应接口的服务列表。ILoadBalancer主要就是一个负载均衡器的接口,作用就是从被负载的服务列表里选出一个服务去调用。

下图为ILoadBalancer的实现类。默认调用的是ZoneAwareLoadBalancer。

OpenFeign远程调用负载均衡原理详解_第15张图片

OpenFeign远程调用负载均衡原理详解_第16张图片 图3.5

图3.5可以看出,Server svc = lb.chooseServer(loadBalancerKey),是从服务列表里面选择一个服务去调用。

跟进chooseServer()方法。默认会按照图3.6执行。

OpenFeign远程调用负载均衡原理详解_第17张图片 图3.6

继续跟进super.chooseServer(key)方法。红框中的rule有多种实现。图3.7调用的时候默认调用的是RoundRobinRule。即轮询策略。至此,我们已探究出FeignClient默认情况下会有负载均衡,且用的是netflix的ribbon的轮询策略。

OpenFeign远程调用负载均衡原理详解_第18张图片

OpenFeign远程调用负载均衡原理详解_第19张图片 图3.7 OpenFeign远程调用负载均衡原理详解_第20张图片 图3.8

结合图3.7从3.8中可以看出rule默认的就是 RoundRobinRule()。

4 我们如何自定义配置来修改默认的负载均衡策略呢?

位置:org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration。

加载 ribbonLoadBalancer 方法时会从ioc容器中查找注册好的Rule来通过参数注入到ZoneAwareLoadBalancer实例中。如果使用默认的,此时的rule默认使用的是ZoneAvoidanceRule,即依赖的rule为RoundRobinRule roundRobinRule = new RoundRobinRule()。

所以如果想定义一个需要的rule,只需要添加以下配置就可以了。

@Configuration
public class TestConfiguration {
    @Bean
    public IRule ribbonRule() {
        return new RandomRule();  //规则可以自己定义,也可以选择已有的
    }

}

 上述配置代码添加后会注册到ioc容器,下图代码为初始化 ILoadBalancer 实例时通过参数注入的方式 把ioc容器中注入好的rule实例传递给这个方法,完成负载策略的实现。

OpenFeign远程调用负载均衡原理详解_第21张图片

你可能感兴趣的:(spring,cloud,java,ribbon,后端,spring)