Client组件
在Feign中,Client是一个非常重要的组件,Feign最终发送Request请求以及接收Response响应都是由Client组件来完成的。Client在Feign源码中是一个接口,在默认情况下,Client的实现类是Client.Default
。Client.Default
是由HttpURLConnection
来实现网络请求的。另外,Client还支持HttpClient和OkHttp来进行网络请求。
Client的实现类包括:
Client.Default类:默认的Client实现类,内部使用
HttpURLConnnection
完成HTTP URL请求处理;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public static class Default implements Client {
private final SSLSocketFactory sslContextFactory;
private final HostnameVerifier hostnameVerifier;
public Default(SSLSocketFactory sslContextFactory, HostnameVerifier hostnameVerifier) {
this.sslContextFactory = sslContextFactory;
this.hostnameVerifier = hostnameVerifier;
}
public Response execute(Request request, Options options) throws IOException {
HttpURLConnection connection = this.convertAndSend(request, options);
return this.convertResponse(connection, request);
}
......//代码省略
}由于
HttpURLConnnection
由于缺乏连接池的支持,在达到一定流量的后服务可能会出现性能问题。ApacheHttpClient 类:内部使用 Apache Httpclient 开源组件完成HTTP URL请求处理的Client实现类;
- OkHttpClient类:内部使用 OkHttp3 开源组件完成HTTP URL请求处理的Client实现类。
自动配置 FeignAutoConfiguration
OpenFeign的自动配置类:org.springframework.cloud.openfeign.FeignAutoConfiguration
,它配置的最原始的Client。
1 |
|
使用HttpClient
自动配置类中,有一个内部类HttpClientFeignConfiguration.class
,它用于配置一个 ApacheHttpClient
客户端。其源码如下:
1 |
|
可以看到这个配置生效的条件是:
@ConditionalOnClass(ApacheHttpClient.class)
: 类路径下存在 ApacheHttpClient 类。@ConditionalOnMissingClass("com.netflix.loadbalancer.ILoadBalancer")
:类路径下不存在 ILoadBalancer 类。feign.httpclient.enabled
的值是true或者缺省(默认是true)。源码如下:
那么如何在Feign中使用HttpClient的框架呢?根据上面FeignAutoConfiguration.HttpClientFeignConfiguration
的源码,可知只需要引入HttpClient的依赖即可,feign.httpclient.enabled
可设置为true或者缺省。
1 | <dependency> |
使用OkHttp
自动配置类中,另外一个内部类 OkHttpFeignConfiguration.class
,它用于配置一个 OkHttp 客户端。其源码如下:
1 |
|
可以看到这个配置生效的条件是:
@ConditionalOnClass(OkHttpClient.class)
: 类路径下存在 OkHttpClient 类。@ConditionalOnMissingClass("com.netflix.loadbalancer.ILoadBalancer")
:类路径下不存在ILoadBalancer
类。feign.okhttp.enabled
的值是true(默认是false)。
所以同理,如果想要在Feign中使用OkHttp作为网络请求框架,则需要在pom文件中加上OkHttp的依赖,并且feign.okhttp.enabled
为ture(这项配置默认是false),代码如下:
pom.xml文件中引入依赖:
1 | <dependency> |
application.yml文件中增加配置项:
1 | feign: |
Ribbon的负载均衡自动配置 FeignRibbonClientAutoConfiguration
除了FeignAutoConfiguration
,还有一个很重要的自动配置类:org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration
,这个自动配置类位于Robbin的jar包中,它让Client具备负载均衡的能力。
Robbin的依赖:
1 | <!-- ribbon--> |
下面分析一下这个类的源码:
1 | import com.netflix.loadbalancer.ILoadBalancer; |
根据类上的注解
@AutoConfigureBefore({FeignAutoConfiguration.class})
可知,FeignRibbonClientAutoConfiguration
自动配置是优先于FeignAutoConfiguration
的。所以当包含OpenFeign功能的项目中引入了Robbin之后,FeignRibbonClientAutoConfiguration
自动配置将生效,而FeignAutoConfiguration.class
的自动配置将会被忽略。再根据类上的注解
@ConditionalOnClass({ILoadBalancer.class, Feign.class})
,可知 FeignRibbonClientAutoConfiguration 的自动配置有两个前提条件:- 当前的类路径中,存在
ILoadBalancer.class
类 - 当前的类路径中,存在
Feign.class
类
- 当前的类路径中,存在
结论:当我们引入了Ribbon的依赖,FeignRibbonClientAutoConfiguration 自动配置生效,负载均衡功能也就生效了。
LoadBalancerFeignClient
LoadBalancerFeignClient 类:这是Ribbon jar包中一个特殊的 feign.Client 客户端实现类。内部先使用 Ribbon 负载均衡算法计算server服务器,然后使用包装的 delegate 客户端实例,去完成 HTTP URL请求处理。
FeignRibbonClientAutoConfiguration 自动配置类,并没有直接配置 LoadBalancerFeignClient 容器实例,而是使用@Import注解,通过导入其他配置类的方式,完成 LoadBalancerFeignClient 客户端容器实例的配置。
分别导入了以下三个自动配置类:
- HttpClientFeignLoadBalancedConfiguration.class
该配置类,负责配置一个包装 ApacheHttpClient 实例的 LoadBalancerFeignClient负载均衡客户端。 - OkHttpFeignLoadBalancedConfiguration.class
该配置类,负责配置一个包装 OkHttpClient 实例的 LoadBalancerFeignClient负载均衡客户端。 - DefaultFeignLoadBalancedConfiguration.class
该配置类,负责配置一个包装 Client.Default 实例的 LoadBalancerFeignClient负载均衡客户端。
所以原生的 HttpClientFeignConfiguration 配置变成了 HttpClientFeignLoadBalancedConfiguration:
1 |
|
原生的 OkHttpFeignConfiguration 配置变成了 OkHttpFeignLoadBalancedConfiguration:
1 |
|
Client实例变成了LoadBalancerFeignClient,只不过LoadBalancerFeignClient中封装了ApacheHttpClient或者OkHttp。
v1.5.2