聊聊Feign的大致功能和代理类的构建

举报
周杰伦本人 发表于 2022/09/29 14:55:33 2022/09/29
【摘要】 聊聊Feign的大致功能和代理类的构建 配置日志 feign的本质 总结 聊聊Feign的大致功能和代理类的构建Feign相当于RestTemplate+Ribbon+Hystrix,Feign本身集成了Ribbon的依赖和自动装配,Feign的默认的请求超时时长是1秒,我们可以通过配置Ribbon的参数来调整请求处理超时时长,ReadTimeout参数就是请求处理超时时长,单位是毫秒当服...

聊聊Feign的大致功能和代理类的构建

Feign相当于RestTemplate+Ribbon+Hystrix,Feign本身集成了Ribbon的依赖和自动装配,Feign的默认的请求超时时长是1秒,我们可以通过配置Ribbon的参数来调整请求处理超时时长,ReadTimeout参数就是请求处理超时时长,单位是毫秒

当服务超时的时候,Ribbon会将请求转移给其他服务,我们可以配置MaxAutoRetries参数来确定当下实例重试次数,第一次调用不算,配置MaxAutoRetriesNextServer参数来调整切换到其他实例的重试次数

配置日志

Feign还支持日志的配置:

@Configuration
public class FeignLogConfiguration {
    @Bean
    Logger.Level feignLog() {
        return Logger.Level.FULL;
    }
}

然后在Feign的客户端配置文件中添加具体feign接口的日志为debug

logging:
  level:
     FeignInterface: debug

Feign也支持熔断,可以通过配置开启熔断,然后使用@FeignClient的fallback属性来配置回退方法,可以设置Hystrix的超时时间

当配置了Ribbon的超时时间和Hystrix的超时时间,处理时长超过两个中的最短时长就会回退降级,Feign还支持请求和响应的压缩,来提升请求的性能

feign的本质

Feign的本质是通过FeignInvocationHandler来增强代理发送请求

那么FeignInvocationHandler是怎么生成的呢,我们先从它的注解@EnableFeignClients开启Feign的注解开始分析,注解中导入了FeignClientsRegistrar类,FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar接口,重写registerBeanDefinitions()方法来注册Bean实例

registerBeanDefinitions()方法中

  • registerDefaultConfiguration()是FeignClient的全局配置注入到容器中,就是取@EnableFeignClients注解中的配置
  • registerFeignClients()方法把被@FeignClient注解修饰的类注入到容器中:定义扫描器扫描basePackage下的被@FeignClient注解修饰的类

我们使用的其实是FeignClientFactoryBean的getObject()方法返回的对象

看一下FeignClientFactoryBean的getObject()方法:

首先会获得Feign.Builder构建器,如果没有配置了url就进行,也就是说有的服务名,这时候就需要进行负载均衡的了:

loadBalance()方法中获取LoadBalancerFeignClient,然后使用Builder来包装这个LoadBalancerFeignClient,最终会调用ReflectiveFeign的newInstance()方法来获取实例,这里使用JDK的动态代理,生成了FeignInvocationHandler的代理类

FeignInvocationHandler的invoke()方法中调用方法对应的MethodHandler的invoke()方法,以SynchronousMethodHandler为例,

SynchronousMethodHandler的invoke()方法中:

  1. 构建RestTemplate对象
  2. 调用executeAndDecode(template)方法来执行请求和解码

在executeAndDecode()方法中使用LoadBalancerFeignClient来执行请求,

  • LoadBalancerFeignClient的execute()方法中构建Ribbon请求来调用AbstractLoadBalancerAwareClient的executeWithLoadBalancer()方法

    • 这里方法里又调用LoadBalancerCommand的submit()方法

      • LoadBalancerCommand的submit()方法中调用selectServer()方法来选择合适的服务,然后使用call()方法发起调用,最终是使用HttpURLConnection来发起请求的

        Client接口的内部类Default的execute()方法:

@Override
    public Response execute(Request request, Options options) throws IOException {
      HttpURLConnection connection = convertAndSend(request, options);
      return convertResponse(connection).toBuilder().request(request).build();
    }
  • 我们看一下selectServer()方法,方法中调用getServerFromLoadBalancer(),在getServerFromLoadBalancer()方法里构建ILoadBalancer的实现类正是Ribbon中用的ZoneAwareLoadBalancer,使用调用chooseServer()方法,这些就是Ribbon中的内容了

总结

今天我们说了一下Feign的工作原理,发起请求的时候是通过一个FeignInvocationHandler的代理类来执行的,我们基于源码分析了代理类是怎么起作用的,发起请求的时候并且用到了Ribbon的选择服务然后负载均衡的功能,Feign与Ribbon实现了结合

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。