正文
1. 概述
在默认情况下 spring cloud feign在进行各个子服务之间的调用时,http组件使用的是jdk的HttpURLConnection,没有使用线程池。本文先从源码分析feign的http组件对象生成的过程,然后通过为feign配置http线程池优化调用效率。
2. 源码分析
我们分析源码spring cloud feign。在spring-cloud-netflix-core/META-INF/spring.factories中可以看到,在spring boot自动配置会初始化FeignRibbonClientAutoConfiguration,这个类会生成Ribbon的使用http组件。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClientAutoConfiguration,\
分析配置类是FeignRibbonClientAutoConfiguration 下面分析此类import的3个类:HttpClientFeignLoadBalancedConfiguration,OkHttpFeignLoadBalancedConfiguration,DefaultFeignLoadBalancedConfiguration
@Import({ HttpClientFeignLoadBalancedConfiguration.class,
OkHttpFeignLoadBalancedConfiguration.class,
DefaultFeignLoadBalancedConfiguration.class })
public class FeignRibbonClientAutoConfiguration {
…
}
HttpClientFeignLoadBalancedConfiguration
为feigin配置appache client的线程池
当引入ApacheHttpClient.class类时,会初始化这个配置类
方法feignClient()中:根据@ConditionalOnMissingBean(Client.class)知道如果有HttpClient 对象,则创建的ApacheHttpClient使用自己定义的HttpClient
。如果没有,则使用默认值。最后生成LoadBalancerFeignClient对象
@Configuration
@ConditionalOnClass(ApacheHttpClient.class)
@ConditionalOnProperty(value = "feign.httpclient.enabled", matchIfMissing = true)
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(delegate, cachingFactory, clientFactory);
}
}
OkHttpFeignLoadBalancedConfiguration
为feigin配置OkHttp,类似apache httpclient, 这里略。
DefaultFeignLoadBalancedConfiguration
为feigin配置HttpURLConnection,
方法feignClient():只有以上两个Client没有生产对象时,才在这个方法中使用Client.Default生成LoadBalancerFeignClient
@Configuration
class DefaultFeignLoadBalancedConfiguration {
@Bean
@ConditionalOnMissingBean
public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory) {
return new LoadBalancerFeignClient(new Client.Default(null, null),
cachingFactory, clientFactory);
}
}
查看Client.Default的源码,Default 使用HttpURLConnection 建立连接且每次请求都建立一个新的连接
public static class Default implements Client {
@Override
public Response execute(Request request, Options options) throws IOException {
HttpURLConnection connection = convertAndSend(request, options);
return convertResponse(connection).toBuilder().request(request).build();
}
….
}
综上所述,在默认情况下,spring cloud 没有引入httpclient和okhttp的jar包,所有默认使用HttpURLConnection
3. 使用appach httpclient线程池
默认情况下,服务之间调用使用的HttpURLConnection,效率非常低。为了提高效率,可以通过连接池提高效率,本节我们使用appache httpclient做为连接池。配置OkHttpClient连接池,也是类似的方法,这里略。 经过上节的分析,配置线程池方法:引入appache httpclient并启动对应配置,最后还需要生成HttpClient对象。
3.1. pom.xml中引入feign-httpclient.jar
<!-- 增加feign-httpclient -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
3.2. 配置参数application-hystrix-feign.yml启动httpclient
# feign配置
feign:
hystrix:
# 在feign中开启hystrix功能,默认情况下feign不开启hystrix功能
enabled: true
## 配置httpclient线程池
httpclient:
enabled: true
okhttp:
enabled: false
3.3. 自定义配置类
使用配置类,生成HttpClient 对象。因为使用PoolingHttpClientConnectionManager连接池,我们需要启动定时器,定时回收过期的连接。配置定时回收连接池的原因,见
问题备忘: httpclient连接池异常引发的惨案