Configure readtimeout for okhttp (#669)
This commit is contained in:
committed by
GitHub
parent
8b1c1dbf4c
commit
d626518dc5
@@ -26,6 +26,7 @@
|
||||
|feign.httpclient.hc5.socket-timeout-unit | | Default value for socket timeout unit.
|
||||
|feign.httpclient.max-connections | `200` |
|
||||
|feign.httpclient.max-connections-per-route | `50` |
|
||||
|feign.httpclient.ok-http-client-properties.read-timeout | `60s` | {@link OkHttpClient} read timeout; defaults to 60 seconds.
|
||||
|feign.httpclient.time-to-live | `900` |
|
||||
|feign.httpclient.time-to-live-unit | |
|
||||
|feign.metrics.enabled | `true` | Enables metrics capability for Feign.
|
||||
|
||||
@@ -739,7 +739,7 @@ To work around this problem you can use an `ObjectProvider` when autowiring your
|
||||
[source,java,indent=0]
|
||||
----
|
||||
@Autowired
|
||||
ObjectProvider<TestFeginClient> testFeginClient;
|
||||
ObjectProvider<TestFeignClient> testFeignClient;
|
||||
----
|
||||
|
||||
=== Spring Data Support
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.cloud.openfeign;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
@@ -274,8 +275,8 @@ public class FeignAutoConfiguration {
|
||||
@ConditionalOnMissingBean(ConnectionPool.class)
|
||||
public ConnectionPool httpClientConnectionPool(FeignHttpClientProperties httpClientProperties,
|
||||
OkHttpClientConnectionPoolFactory connectionPoolFactory) {
|
||||
Integer maxTotalConnections = httpClientProperties.getMaxConnections();
|
||||
Long timeToLive = httpClientProperties.getTimeToLive();
|
||||
int maxTotalConnections = httpClientProperties.getMaxConnections();
|
||||
long timeToLive = httpClientProperties.getTimeToLive();
|
||||
TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
|
||||
return connectionPoolFactory.create(maxTotalConnections, timeToLive, ttlUnit);
|
||||
}
|
||||
@@ -283,12 +284,13 @@ public class FeignAutoConfiguration {
|
||||
@Bean
|
||||
public okhttp3.OkHttpClient client(OkHttpClientFactory httpClientFactory, ConnectionPool connectionPool,
|
||||
FeignHttpClientProperties httpClientProperties) {
|
||||
Boolean followRedirects = httpClientProperties.isFollowRedirects();
|
||||
Integer connectTimeout = httpClientProperties.getConnectionTimeout();
|
||||
Boolean disableSslValidation = httpClientProperties.isDisableSslValidation();
|
||||
boolean followRedirects = httpClientProperties.isFollowRedirects();
|
||||
int connectTimeout = httpClientProperties.getConnectionTimeout();
|
||||
boolean disableSslValidation = httpClientProperties.isDisableSslValidation();
|
||||
Duration readTimeout = httpClientProperties.getOkHttpClientProperties().getReadTimeout();
|
||||
this.okHttpClient = httpClientFactory.createBuilder(disableSslValidation)
|
||||
.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS).followRedirects(followRedirects)
|
||||
.connectionPool(connectionPool).build();
|
||||
.readTimeout(readTimeout).connectionPool(connectionPool).build();
|
||||
return this.okHttpClient;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.openfeign.clientconfig;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
@@ -48,8 +49,8 @@ public class OkHttpFeignConfiguration {
|
||||
@ConditionalOnMissingBean(ConnectionPool.class)
|
||||
public ConnectionPool httpClientConnectionPool(FeignHttpClientProperties httpClientProperties,
|
||||
OkHttpClientConnectionPoolFactory connectionPoolFactory) {
|
||||
Integer maxTotalConnections = httpClientProperties.getMaxConnections();
|
||||
Long timeToLive = httpClientProperties.getTimeToLive();
|
||||
int maxTotalConnections = httpClientProperties.getMaxConnections();
|
||||
long timeToLive = httpClientProperties.getTimeToLive();
|
||||
TimeUnit ttlUnit = httpClientProperties.getTimeToLiveUnit();
|
||||
return connectionPoolFactory.create(maxTotalConnections, timeToLive, ttlUnit);
|
||||
}
|
||||
@@ -57,11 +58,12 @@ public class OkHttpFeignConfiguration {
|
||||
@Bean
|
||||
public okhttp3.OkHttpClient client(OkHttpClientFactory httpClientFactory, ConnectionPool connectionPool,
|
||||
FeignHttpClientProperties httpClientProperties) {
|
||||
Boolean followRedirects = httpClientProperties.isFollowRedirects();
|
||||
Integer connectTimeout = httpClientProperties.getConnectionTimeout();
|
||||
boolean followRedirects = httpClientProperties.isFollowRedirects();
|
||||
int connectTimeout = httpClientProperties.getConnectionTimeout();
|
||||
Duration reaTimeout = httpClientProperties.getOkHttpClientProperties().getReadTimeout();
|
||||
this.okHttpClient = httpClientFactory.createBuilder(httpClientProperties.isDisableSslValidation())
|
||||
.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS).followRedirects(followRedirects)
|
||||
.connectionPool(connectionPool).build();
|
||||
.readTimeout(reaTimeout).connectionPool(connectionPool).build();
|
||||
return this.okHttpClient;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,13 +16,17 @@
|
||||
|
||||
package org.springframework.cloud.openfeign.support;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import feign.okhttp.OkHttpClient;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* @author Ryan Baxter
|
||||
* @author Nguyen Ky Thanh
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "feign.httpclient")
|
||||
public class FeignHttpClientProperties {
|
||||
@@ -88,8 +92,13 @@ public class FeignHttpClientProperties {
|
||||
*/
|
||||
private Hc5Properties hc5 = new Hc5Properties();
|
||||
|
||||
/**
|
||||
* Additional {@link OkHttpClient}-specific properties.
|
||||
*/
|
||||
private OkHttpClientProperties okHttpClientProperties = new OkHttpClientProperties();
|
||||
|
||||
public int getConnectionTimerRepeat() {
|
||||
return this.connectionTimerRepeat;
|
||||
return connectionTimerRepeat;
|
||||
}
|
||||
|
||||
public void setConnectionTimerRepeat(int connectionTimerRepeat) {
|
||||
@@ -97,7 +106,7 @@ public class FeignHttpClientProperties {
|
||||
}
|
||||
|
||||
public boolean isDisableSslValidation() {
|
||||
return this.disableSslValidation;
|
||||
return disableSslValidation;
|
||||
}
|
||||
|
||||
public void setDisableSslValidation(boolean disableSslValidation) {
|
||||
@@ -105,7 +114,7 @@ public class FeignHttpClientProperties {
|
||||
}
|
||||
|
||||
public int getMaxConnections() {
|
||||
return this.maxConnections;
|
||||
return maxConnections;
|
||||
}
|
||||
|
||||
public void setMaxConnections(int maxConnections) {
|
||||
@@ -113,7 +122,7 @@ public class FeignHttpClientProperties {
|
||||
}
|
||||
|
||||
public int getMaxConnectionsPerRoute() {
|
||||
return this.maxConnectionsPerRoute;
|
||||
return maxConnectionsPerRoute;
|
||||
}
|
||||
|
||||
public void setMaxConnectionsPerRoute(int maxConnectionsPerRoute) {
|
||||
@@ -121,7 +130,7 @@ public class FeignHttpClientProperties {
|
||||
}
|
||||
|
||||
public long getTimeToLive() {
|
||||
return this.timeToLive;
|
||||
return timeToLive;
|
||||
}
|
||||
|
||||
public void setTimeToLive(long timeToLive) {
|
||||
@@ -129,7 +138,7 @@ public class FeignHttpClientProperties {
|
||||
}
|
||||
|
||||
public TimeUnit getTimeToLiveUnit() {
|
||||
return this.timeToLiveUnit;
|
||||
return timeToLiveUnit;
|
||||
}
|
||||
|
||||
public void setTimeToLiveUnit(TimeUnit timeToLiveUnit) {
|
||||
@@ -137,7 +146,7 @@ public class FeignHttpClientProperties {
|
||||
}
|
||||
|
||||
public boolean isFollowRedirects() {
|
||||
return this.followRedirects;
|
||||
return followRedirects;
|
||||
}
|
||||
|
||||
public void setFollowRedirects(boolean followRedirects) {
|
||||
@@ -145,7 +154,7 @@ public class FeignHttpClientProperties {
|
||||
}
|
||||
|
||||
public int getConnectionTimeout() {
|
||||
return this.connectionTimeout;
|
||||
return connectionTimeout;
|
||||
}
|
||||
|
||||
public void setConnectionTimeout(int connectionTimeout) {
|
||||
@@ -160,6 +169,14 @@ public class FeignHttpClientProperties {
|
||||
this.hc5 = hc5;
|
||||
}
|
||||
|
||||
public OkHttpClientProperties getOkHttpClientProperties() {
|
||||
return okHttpClientProperties;
|
||||
}
|
||||
|
||||
public void setOkHttpClientProperties(OkHttpClientProperties okHttpClientProperties) {
|
||||
this.okHttpClientProperties = okHttpClientProperties;
|
||||
}
|
||||
|
||||
public static class Hc5Properties {
|
||||
|
||||
/**
|
||||
@@ -203,7 +220,7 @@ public class FeignHttpClientProperties {
|
||||
private TimeUnit socketTimeoutUnit = DEFAULT_SOCKET_TIMEOUT_UNIT;
|
||||
|
||||
public PoolConcurrencyPolicy getPoolConcurrencyPolicy() {
|
||||
return this.poolConcurrencyPolicy;
|
||||
return poolConcurrencyPolicy;
|
||||
}
|
||||
|
||||
public void setPoolConcurrencyPolicy(PoolConcurrencyPolicy poolConcurrencyPolicy) {
|
||||
@@ -272,4 +289,24 @@ public class FeignHttpClientProperties {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link OkHttpClient}-specific properties.
|
||||
*/
|
||||
public static class OkHttpClientProperties {
|
||||
|
||||
/**
|
||||
* {@link OkHttpClient} read timeout; defaults to 60 seconds.
|
||||
*/
|
||||
private Duration readTimeout = Duration.ofSeconds(60);
|
||||
|
||||
public Duration getReadTimeout() {
|
||||
return readTimeout;
|
||||
}
|
||||
|
||||
public void setReadTimeout(Duration readTimeout) {
|
||||
this.readTimeout = readTimeout;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -45,26 +45,33 @@ class FeignOkHttpConfigurationTests {
|
||||
void setUp() {
|
||||
this.context = new SpringApplicationBuilder()
|
||||
.properties("debug=true", "feign.httpclient.disableSslValidation=true", "feign.okhttp.enabled=true",
|
||||
"feign.httpclient.enabled=false")
|
||||
"feign.httpclient.enabled=false", "feign.httpclient.okhttp-client-properties.read-timeout=9s")
|
||||
.web(WebApplicationType.NONE).sources(HttpClientConfiguration.class, FeignAutoConfiguration.class)
|
||||
.run();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
if (context != null) {
|
||||
context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void disableSslTest() {
|
||||
OkHttpClient httpClient = this.context.getBean(OkHttpClient.class);
|
||||
OkHttpClient httpClient = context.getBean(OkHttpClient.class);
|
||||
HostnameVerifier hostnameVerifier = (HostnameVerifier) this.getField(httpClient, "hostnameVerifier");
|
||||
assertThat(hostnameVerifier instanceof OkHttpClientFactory.TrustAllHostnames).isTrue();
|
||||
}
|
||||
|
||||
protected <T> Object getField(Object target, String name) {
|
||||
@Test
|
||||
void shouldConfigureReadTimeout() {
|
||||
OkHttpClient httpClient = context.getBean(OkHttpClient.class);
|
||||
|
||||
assertThat(httpClient.readTimeoutMillis()).isEqualTo(9000);
|
||||
}
|
||||
|
||||
protected Object getField(Object target, String name) {
|
||||
Field field = ReflectionUtils.findField(target.getClass(), name);
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
Object value = ReflectionUtils.getField(field, target);
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfigurati
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.util.ReflectionTestUtils.getField;
|
||||
|
||||
/**
|
||||
* @author Olga Maciaszek-Sharma
|
||||
@@ -58,9 +59,18 @@ class FeignLoadBalancerAutoConfigurationTests {
|
||||
@Test
|
||||
void shouldInstantiateOkHttpFeignClientWhenEnabled() {
|
||||
ConfigurableApplicationContext context = initContext("feign.httpclient.enabled=false",
|
||||
"feign.okhttp.enabled=true", "spring.cloud.loadbalancer.retry.enabled=false");
|
||||
"feign.okhttp.enabled=true", "spring.cloud.loadbalancer.retry.enabled=false",
|
||||
"feign.httpclient.okhttp-client-properties.read-timeout=9s");
|
||||
assertThatOneBeanPresent(context, BlockingLoadBalancerClient.class);
|
||||
assertLoadBalanced(context, OkHttpClient.class);
|
||||
Map<String, FeignBlockingLoadBalancerClient> beans = context
|
||||
.getBeansOfType(FeignBlockingLoadBalancerClient.class);
|
||||
assertThat(beans).as("Missing bean of type %s", OkHttpClient.class).hasSize(1);
|
||||
Client client = beans.get("feignClient").getDelegate();
|
||||
assertThat(client).isInstanceOf(OkHttpClient.class);
|
||||
OkHttpClient okHttpClient = (OkHttpClient) client;
|
||||
okhttp3.OkHttpClient httpClient = (okhttp3.OkHttpClient) getField(okHttpClient, "delegate");
|
||||
assertThat(httpClient.readTimeoutMillis()).isEqualTo(9000);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user