前言
之前的文章 OpenFeign十大可扩展组件你知道哪些?有说过Openfeign有10大可扩展组件:
我们今天详细分析第一个 feign.Client
,还有Spring默认提供的负载均衡能力的通信客户端org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient
, client组件应属于feign框架中最核心的组件,因为它承担着rpc框架最关键的能力-发起远程通信
。
feign.Client默认实现
在feign的原生包里面,有一个默认的实现feign.Client.Default
默认使用的是Java原生的HttpURLConnection
来发起通信,
这里是官方对HttpURLConnection的介绍,感兴趣的可以查看
Java官方提供的基于Socket的基础通信组件,api的使用比较麻烦,比如需要发起一个http请求,我们需要这样写:
//根据请求地址构造URL对象
URL url = new URL("http://www.baidu.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
//需要自行操作流
List<String> result = IOUtils.readLines(in);
for (String r : result) {
System.out.println(r);
}
} finally {
urlConnection.disconnect();
}
HttpURLConnection
没有封装好的http网络库使用便捷。比okhttp,apache,httpcompent
,我们的应用程序一般会使用到封装好的库进行通信。 下面是okhttp的写法:
@SneakyThrows
public static void main(String[] args) {
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder().url("http://www.baidu.com").build();
Response reponse = okHttpClient.newCall(request).execute();
System.out.println(reponse.body().string());
}
相比okhttp,HttpURLConnection
使用上更费劲,而okhttp提供了极好的便捷性和扩展性,从下方构造函数看,okhttp组件提供了很多扩展点,比如拦截器,缓存,代理
等,同时如果想做负载均衡的话,是不支持的。
LoadBalancerFeignClient登场
于是LoadBalancerFeignClient
出现了,LoadBalancerFeignClient是集成了负载均衡能力的客户端,同时它持有了抽象的通信client组件的引用。
feign本身不提供负载均衡的能力,默认会使用ribbon负责负载均衡处理。
LoadBalancerFeignClient
它是如何生效的呢?也就是说怎么替换feign里默认的通信feign.Client
?DefaultFeignLoadBalancedConfiguration
里面利用了自动装配机制进行覆盖
package org.springframework.cloud.openfeign.ribbon;
/**
* @author Spencer Gibb
*/
@Configuration
class DefaultFeignLoadBalancedConfiguration {
@Bean
@ConditionalOnMissingBean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory) {
return new LoadBalancerFeignClient(new Client.Default(null, null), cachingFactory,
clientFactory);
}
}
openfeign如何替换默认的HttpUrlConnection
这种情况还是使用的httpUrlConnection通信组件,如果想使用okhttp或者apache-http-client怎么办呢?
Spring团队也早想到了,分别给我们提供了一个配置类
package org.springframework.cloud.openfeign.ribbon;
/**
* @author Spencer Gibb
*/
@Configuration
@ConditionalOnClass(OkHttpClient.class)
@ConditionalOnProperty("feign.okhttp.enabled")
class OkHttpFeignLoadBalancedConfiguration {
@Bean
@ConditionalOnMissingBean(Client.class)
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory, okhttp3.OkHttpClient okHttpClient) {
OkHttpClient delegate = new OkHttpClient(okHttpClient);
return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
}
}
你们项目中是否有使用过上方这个配置feign.okhttp.enabled
呢?
下面是使用ApacheHttpClient
替换默认通信组件
package org.springframework.cloud.openfeign.ribbon;
/**
* @author Spencer Gibb
*/
@Configuration
@ConditionalOnClass(ApacheHttpClient.class)
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
class HttpClientFeignLoadBalancedConfiguration {
@Bean
@ConditionalOnMissingBean(Client.class)
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory, HttpClient httpClient) {
ApacheHttpClient delegate = new ApacheHttpClient(httpClient);
return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
}
}
写到这里又想抱Spring团队大佬的大腿了,每个组件都能写的这么灵活。
总结篇
Client组件默认使用HttpURLConnection实现通信,而LoadBalancerFeignClient是将负责均衡和通信能力组合的。由于负载均衡能力是ribbon提供的,本文只分析到此,下文将分析ribbon是如何给openFeign增加负载均衡能力的。