feign-底层http请求组件剖析

     这篇文章主要介绍下feign底层使用的http发送请求的组件,下面就一步步得来做剖析。
     我们知道使用feign的时候两个重要的注解@FeignClient和@EnableFeignClients,这两个注解分别是标识是一个feign的client,在启动的时候需要去扫描和register相应的信息,和允许使用feign的client,我们查看源码可以知道这两个注解都来自于org.springframework.cloud.netflix.feign,我们可以看到这个包下还有其他很多类,按照spring boot的一贯风格,自动化配置肯定包含auto configuration这样的单词,那么我们可以找到FeignAutoConfiguration这个类,看如下代码:
// the following configuration is for alternate feign clients if
// ribbon is not on the class path.
// see corresponding configurations in FeignRibbonClientAutoConfiguration
// for load balanced ribbon clients.
@Configuration
@ConditionalOnClass(ApacheHttpClient.class)
@ConditionalOnMissingClass("com.netflix.loadbalancer.ILoadBalancer")
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
protected static class HttpClientFeignConfiguration {

   @Autowired(required = false)
   private HttpClient httpClient;

   @Bean
   @ConditionalOnMissingBean(Client.class)
   public Client feignClient() {
      if (this.httpClient != null) {
         return new ApacheHttpClient(this.httpClient);
      }
      return new ApacheHttpClient();
   }
}

     这块代码其实就是配置底层http发送请求的具体client的,那么我们看到@ConditionalOnMissingClass("com.netflix.loadbalancer.ILoadBalancer"),其实含义就是没有ILoadBalancer这个类才会执行这个配置,但是由于我们用了Ribbon,这个类是肯定存在的,那么肯定Feign和Ribbon一起使用的时候自动配置肯定不是这个类,细心看注释,其实已经告诉了我们配置类是FeignRibbonClientAutoConfiguration,OK,我们转到这个类去看:
@Bean
@ConditionalOnMissingBean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
      SpringClientFactory clientFactory) {
   return new LoadBalancerFeignClient(new Client.Default(null, null),
         cachingFactoryclientFactory);
}

@Bean
@ConditionalOnMissingBean
public Request.Options feignRequestOptions() {
   return LoadBalancerFeignClient.DEFAULT_OPTIONS;
}

@Configuration
@ConditionalOnClass(ApacheHttpClient.class)
@ConditionalOnProperty(value "feign.httpclient.enabled"matchIfMissing true)
protected static class HttpClientFeignLoadBalancedConfiguration {

   @Autowired(required false)
   private HttpClient httpClient;

   @Bean
   @ConditionalOnMissingBean(Client.class)
   public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
         SpringClientFactory clientFactory) {
      ApacheHttpClient delegate;
      if (this.httpClient != null) {
         delegate = new ApacheHttpClient(this.httpClient);
      }
      else {
         delegate = new ApacheHttpClient();
      }
      return new LoadBalancerFeignClient(delegatecachingFactoryclientFactory);
   }
}
     这块代码有两个bean是配置Client的,那么到底是使用哪个呢?第二个static类必须要ApacheHttpClient.class存在,但是我们发现如果项目只包含cloud feign的话这个类是不存在的,所以理论上应该初始化的是代码最上面的那个Client,那么我们进Client.Default,不难发现其实用的是HttpURLConnection,这个类继承于URLConnection,这两个类都是JDK原生的发送http请求的组件,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection做请求的优化,我们可以将他替换成HttpClient,从而获取连接池、超时时间等与性能息息相关的控制能力。其实看第二个bean就可以发现只要引入ApacheHttpClient这个类即可,那么我们加入io.github.openfeign:feign-httpclient:9.5.0就可以发现有这个类了(这个包也就这一个类),我们debug进去可以发现是真的使用的HttpClient,发现bean容器中没有HttpClient对象,导致使用的默认是HttpClientBuilder.create().build()创建出来的HttpClient,为了使我们又足够的能力来控制这个httpclient,我们需要在bean容器里面创建一个出来。
     那么问题来了,我们不可能在每一个消费者中都加入这样的bean,这样代码太重复了,这时我们可以使用spring-boot强大的自动配置,我们来自己自定义一个starter用来创建feign的httpclient,代码比较简单,直接见github:https://github.com/JThink/spring-boot-starter-feign-httpclient,主要还是自己创建了带连接池的httpclient对象。
     其实我们还可以看到auto configuration中还有个OkHttpClient,如果想用这个Client按照同样的方式即可,对这个组件不熟,就不多做介绍了。

      分享一个项目:https://github.com/JThink/SkyEye对java、scala等运行于jvm的程序进行实时日志采集、索引和可视化,对系统进行进程级别的监控,对系统内部的操作进行策略性的报警、对分布式的rpc调用进行trace跟踪以便于进行性能分析。欢迎对分布式跟踪感兴趣的交流~~,交流群:624054633
  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值