文章目录
- 前言
- 正文
- 一、OkHttpFeignConfiguration 的启用
- 1.1 分析配置类
- 1.2 得出结论,需要增加配置
- 1.3 调试
- 二、OkHttpFeignLoadBalancerConfiguration 的启用
- 2.1 分析配置类
- 2.2 得出结论
- 2.3 测试
- 附录
- 附1:本系列文章链接
- 附2:OkHttpClient 增加拦截器配置
- 附2.1 新建配置类OkHttpConfig
- 附2.2 调试结果
前言
众所周知,我们在使用SpringCloud OpenFeign时,默认使用的是老旧的连接器HttpURLConnection
。性能以及并发量方面都差强人意。
一般而言都会对其进行优化调整。本文采用OpenFeign整合okHttp的方式替换原有的Client,去做请求。
使用java 17,spring cloud 4.0.4,springboot 3.1.4
使用项目是本系列第一篇中的项目
本文介绍两种方式的配置,一个是LoadBalancer 的,都是默认带有连接池的。
OkHttpFeignConfiguration
OkHttpFeignLoadBalancerConfiguration
正文
一、OkHttpFeignConfiguration 的启用
1.1 分析配置类
首先我们需要加入什么依赖配置呢?
依据 OkHttpFeignConfiguration
的配置内容,进行分析:
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(OkHttpClient.class)
@ConditionalOnMissingBean(okhttp3.OkHttpClient.class)
@ConditionalOnProperty("spring.cloud.openfeign.okhttp.enabled")
protected static class OkHttpFeignConfiguration {// 类路径下有连接池时,构建连接池@Bean@ConditionalOnMissingBean(ConnectionPool.class)public ConnectionPool httpClientConnectionPool(FeignHttpClientProperties httpClientProperties) {int maxTotalConnections = httpClientProperties.getMaxConnections();long timeToLive = httpClientProperties.getTimeToLive();TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();return new ConnectionPool(maxTotalConnections, timeToLive, ttlUnit);}// 构建OkHttpClient实例@Beanpublic okhttp3.OkHttpClient okHttpClient(okhttp3.OkHttpClient.Builder builder, ConnectionPool connectionPool,FeignHttpClientProperties httpClientProperties) {boolean followRedirects = httpClientProperties.isFollowRedirects();int connectTimeout = httpClientProperties.getConnectionTimeout();boolean disableSslValidation = httpClientProperties.isDisableSslValidation();Duration readTimeout = httpClientProperties.getOkHttp().getReadTimeout();List<Protocol> protocols = httpClientProperties.getOkHttp().getProtocols().stream().map(Protocol::valueOf).collect(Collectors.toList());if (disableSslValidation) {disableSsl(builder);}this.okHttpClient = builder.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS).followRedirects(followRedirects).readTimeout(readTimeout).connectionPool(connectionPool).protocols(protocols).build();return this.okHttpClient;}
}
1.2 得出结论,需要增加配置
从配置类中观察到,它的启用条件有2个,一个是需要引入 okhttp的包,另一个需要一行启用配置:
<!-- https://mvnrepository.com/artifact/io.github.openfeign/feign-okhttp -->
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-okhttp</artifactId><version>13.1</version>
</dependency>
# 启用okhttp配置
spring.cloud.openfeign.okhttp.enabled=true
1.3 调试
正常请求,在SynchronousMethodHandler.executeAndDecode(...)
中打断点,调试观察client的类型:
发现已经不再是之前的Default
了,换成了OkHttpClient
类型。并且,也内置了连接池以及一些基本配置信息。
二、OkHttpFeignLoadBalancerConfiguration 的启用
2.1 分析配置类
依据 OkHttpFeignLoadBalancerConfiguration
中的配置项,分析:
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(OkHttpClient.class)
@ConditionalOnProperty("spring.cloud.openfeign.okhttp.enabled")
@ConditionalOnBean({ LoadBalancerClient.class, LoadBalancerClientFactory.class })
@EnableConfigurationProperties(LoadBalancerClientsProperties.class)
class OkHttpFeignLoadBalancerConfiguration {@Bean@ConditionalOnMissingBean@Conditional(OnRetryNotEnabledCondition.class)public Client feignClient(okhttp3.OkHttpClient okHttpClient, LoadBalancerClient loadBalancerClient,LoadBalancerClientFactory loadBalancerClientFactory,List<LoadBalancerFeignRequestTransformer> transformers) {OkHttpClient delegate = new OkHttpClient(okHttpClient);return new FeignBlockingLoadBalancerClient(delegate, loadBalancerClient, loadBalancerClientFactory,transformers);}// 省略其他配置
}
2.2 得出结论
想要让这个配置生效,需要满足OkHttpClient
、LoadBalancerClient
、OnRetryNotEnabledCondition
。
也就是2个依赖项,2个配置:
<!-- https://mvnrepository.com/artifact/io.github.openfeign/feign-okhttp -->
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-okhttp</artifactId><version>13.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-loadbalancer -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId><version>4.0.4</version>
</dependency>
而配置方面需要增加:
# 启用okhttp配置
spring.cloud.openfeign.okhttp.enabled=true# 关闭负载重试
spring.cloud.loadbalancer.retry.enabled=false
2.3 测试
正常请求,在SynchronousMethodHandler.executeAndDecode(...)
中打断点,调试观察client的类型:
发现已经不再是之前的Default
了,换成了OkHttpClient
类型。
附录
附1:本系列文章链接
SpringCloud系列文章目录(总纲篇)
附2:OkHttpClient 增加拦截器配置
附2.1 新建配置类OkHttpConfig
增加以下拦截器配置,对请求和响应进行日志打印。
package org.feng.config;import lombok.extern.slf4j.Slf4j;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.io.IOException;/*** okhttp配置** @author feng*/
@Slf4j
@Configuration
public class OkHttpConfig {@Beanpublic okhttp3.OkHttpClient.Builder okHttpClientBuilder() {return new okhttp3.OkHttpClient.Builder().addInterceptor(new LoggingInterceptor());}/*** okhttp3 请求日志拦截器*/static class LoggingInterceptor implements Interceptor {@NotNull@Overridepublic Response intercept(Chain chain) throws IOException {Request request = chain.request();long start = System.nanoTime();log.info(String.format("Sending request %s on %s%n%s",request.url(), chain.connection(), request.headers()));Response response = chain.proceed(request);long end = System.nanoTime();log.info(String.format("Received response for %s in %.1fms%n%s",response.request().url(), (end - start) / 1e6d, response.headers()));return response;}}
}
附2.2 调试结果
可以观察到日志中,打印出来了请求路径、请求头等信息。
2023-11-24T16:48:56.358+08:00 INFO 35987 --- [nio-8080-exec-1] org.feng.config.OkHttpConfig : Sending request http://localhost:10080/hello/post on null
Content-Length: 100
Accept: */*2023-11-24T16:48:56.713+08:00 INFO 35987 --- [nio-8080-exec-1] org.feng.config.OkHttpConfig : Received response for http://localhost:10080/hello/post in 347.4ms
Content-Type: application/json
Transfer-Encoding: chunked
Date: Fri, 24 Nov 2023 08:48:56 GMT
Keep-Alive: timeout=60
Connection: keep-alive