探究springcloud openFeign如何和hystrix以及ribbon协作的

在springcloud体系下服务之间的调用,目前比较常用的都是通过openfeign来进行调用,而openfeign是集成有负载均衡ribbon、熔断器hystrix的,那今天就和大家一起探究下 openFeign是如何与ribbon和hystrix一起协作来完成一起请求过程的。

在请求过程中接口需不需要熔断,发起请求的组件会有不同的配置,我们以启用hystrix以及okhttp的方式发起调用,如下配置

#熔断器启用

feign.hystrix.enabled=true

#启用okhttp

feign.okhttp.enabled=true

先看下上面两项配置干了些什么

首先来看feign.okhttp.enabled=true

定义了 LoadBalancerFeignClient 的Bean对象 ,LoadBalancerFeignClient 中的Client对象就只在这初始化的,源码中也就是OKHttpClient对象。

再看看feign.hystrix.enabled=true

接下来,我们在这个前提下捋一捋整个调用过程,openFeign从EnableFeignClients这个注解开始的

一、解析阶段

看代码import了一个类FeignClientsRegistrar,这个类实现了ImportBeanDefinitionRegistrar接口,那么就需要重写registerBeanDefinitions方法。如下:

这个方法做了2两件事情:

1、注册全局配置,如果EnableFeignClients注解上配置了defaultConfiguration属性

2、注册FeignClients

这个方法会扫描类路径上标记@FeignClient注解的接口,根据@EnableFeignClients注解上的配置,并循环注册FeignClient。

这个方法就是将FeignClient注解上的属性信息,封装到BeanDefinition中,并注册到Spring容器中。

二、运行阶段

在解析阶段将@FeignClient注解的类以FeignClientFactoryBean的形式往BeanFactory注入BeanDefinition。

1、获取在FeignAutoConfiguration中注入的FeignContext

2、调用feign方法,获取构建器

protected Feign.Builder feign(FeignContext context) {

    FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class);

    Logger logger = loggerFactory.create(this.type);

    // @formatter:off

    Feign.Builder builder = get(context, Feign.Builder.class)

            // required values

            .logger(logger)

            .encoder(get(context, Encoder.class))

            .decoder(get(context, Decoder.class))

            .contract(get(context, Contract.class));

    // @formatter:on

    configureFeign(context, builder);

    return builder;

}

    根据FeignContext处理了我们自定义的@FeignClient以及全局@EnableFeignClients中配置的日志,加、解密器,验证器等,最后configureFeign如下,处理了链接超时、读取超时等配置项:

protected void configureFeign(FeignContext context, Feign.Builder builder) {

    FeignClientProperties properties = this.applicationContext.getBean(FeignClientProperties.class);

    if (properties != null) {

        if (properties.isDefaultToProperties()) {

            configureUsingConfiguration(context, builder);

            configureUsingProperties(

                    properties.getConfig().get(properties.getDefaultConfig()),

                    builder);

            configureUsingProperties(properties.getConfig().get(this.contextId),

                    builder);

        } else {

            configureUsingProperties(

                    properties.getConfig().get(properties.getDefaultConfig()),

                    builder);

            configureUsingProperties(properties.getConfig().get(this.contextId),

                    builder);

            configureUsingConfiguration(context, builder);

        }

    } else {

        configureUsingConfiguration(context, builder);

    }

}

3、调用loadBalance方法

4、根据Targeter(这里是HystrixTargeter),

调用的是feign的target方法,由于开启了hystrix所以实际上调用的是HystrixFeign的target方法

可以看到首先调用ParseHandlersByName的apply方法构建给每个方法都构建一个MethodHander对象,存储在Map中,key即为methodd对象,下面是其实现

这里的factory其实就是SynchronousMethodHandler的一个内部类

进入查看create方法的实现

可以看到实际上返回的是SynchronousMethodHandler对象,接下来就是

使用InvocationHandlerFactory工厂创建代理对象,返回InvocationHandler对象实际上是HystrixInvocationHandler,最后返回代理对象。

5、HystrixInvocationHandler的invoker方法

可见openFeign是通过HystrixInvocationHandler与Hystrix协作的,构建HystrixCommand对象,在run方法中执行核心逻辑,如果需要降级则执行getFallback方法。在run方法中根据method获取MethodHandler对象,这里是SynchronousMethodHandler对象,下面是invoke方法

这里调用的client的execute方法来处理请求,而client实际上是 LoadBalancerFeignClient,我们来看下其execute的实现,

再调用lbClient方法根据clientName获取到FeignLoadBalancer对象,进而调用其executeWithLoadBalancer方法

FeignLoadBalancer继承AbstractLoadBalancerAwareClient,executeWithLoadBalancer方法在AbstractLoadBalancerAwareClient中实现

方法中构建LoadBalancerCommand对象,并调用AbstractLoadBalancerAwareClient.this.execute方法,也就是OkHttpLoadBalancingClient的execute方法,可见openFeign是通过LoadBalancerFeignClient实现与Ribbon协作的

最终通过OkHttpClient发送请求,并返回结果封装到OkHttpRibbonResponse对象中,

总结,openFeign是通过HystrixInvocationHandler构建HystrixCommand完成与Hystrix的协作,通过LoadBalancerFeignClient实现与Ribbon协作的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容