OpenFeign集成OkHttp
OpenFeign本质是HTTP来进行服务调用的,也就是需要集成一个Http客户端。
使用的是Client接口来进行请求的
1 2 3 4 5 6
| public interface Client {
Response execute(Request request, Options options) throws IOException; }
|
默认是HttpURLConnection方式,也就是jdk中提供的最原始的那个
1 2 3 4 5 6 7 8
| 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(); } }
|
HTTP连接需要进行TCP三次握手,是一个比较耗时的操作,一般我们不直接使用HttpURLConnection,而是使用HttpClient/okHttp等支持连接池的客户端工具,以Feign集成OkHttp为例
添加依赖
1 2 3 4
| <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> </dependency>
|
其包内有一个Client的实现类OkHttpClient,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public final class OkHttpClient implements Client {
@Override public feign.Response execute(feign.Request input, feign.Request.Options options) throws IOException { okhttp3.OkHttpClient requestScoped; if (delegate.connectTimeoutMillis() != options.connectTimeoutMillis() || delegate.readTimeoutMillis() != options.readTimeoutMillis()) { requestScoped = delegate.newBuilder() .connectTimeout(options.connectTimeoutMillis(), TimeUnit.MILLISECONDS) .readTimeout(options.readTimeoutMillis(), TimeUnit.MILLISECONDS) .followRedirects(options.isFollowRedirects()) .build(); } else { requestScoped = delegate; } Request request = toOkHttpRequest(input); Response response = requestScoped.newCall(request).execute(); return toFeignResponse(response, input).toBuilder().request(input).build(); } }
|
配置连接池
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| import okhttp3.ConnectionPool; import okhttp3.OkHttpClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
import javax.net.ssl.*; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.util.concurrent.TimeUnit;
@Configuration public class OkHttpConfig {
@Bean public OkHttpClient okHttpClient() { return new OkHttpClient.Builder() .sslSocketFactory(sslSocketFactory(), x509TrustManager()) .hostnameVerifier(hostnameVerifier()) .retryOnConnectionFailure(false) .connectionPool(pool()) .connectTimeout(15L, TimeUnit.SECONDS) .readTimeout(15L, TimeUnit.SECONDS) .followRedirects(true) .build(); }
@Bean public X509TrustManager x509TrustManager() { return new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) { }
@Override public void checkServerTrusted(X509Certificate[] x509Certificates, String s) { }
@Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }; }
@Bean public SSLSocketFactory sslSocketFactory() { try { TrustManager[] trustManagers = new TrustManager[]{x509TrustManager()}; SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustManagers, new SecureRandom()); return sslContext.getSocketFactory(); } catch (NoSuchAlgorithmException | KeyManagementException e) { e.printStackTrace(); } return null; }
@Bean public ConnectionPool pool() { return new ConnectionPool(200, 5, TimeUnit.MINUTES); }
@Bean public HostnameVerifier hostnameVerifier() { return (s, sslSession) -> true; } }
|
yml配置
要开启OkHttp ,还需要在YML 中添加开启配置项,默认是关闭的
1 2 3
| feign: okhttp: enabled: true
|
至于为什么需要配这个,看一下FeignAutoConfiguration中装配OkHttp的条件
1 2 3 4 5 6
| @Configuration(proxyBeanMethods = false) @ConditionalOnClass(OkHttpClient.class) @ConditionalOnMissingClass("com.netflix.loadbalancer.ILoadBalancer") @ConditionalOnMissingBean(okhttp3.OkHttpClient.class) @ConditionalOnProperty("feign.okhttp.enabled") protected static class OkHttpFeignConfiguration
|