From cc952282e455e60da7e5f489b31c788a385d2218 Mon Sep 17 00:00:00 2001 From: Roelof Jan Date: Wed, 30 Sep 2020 10:23:16 +0200 Subject: [PATCH] MGNL-17767 Configure validate idle connection --- .../client/resteasy/AbstractApiClient.java | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/vpro-shared-client-resteasy/src/main/java/nl/vpro/api/client/resteasy/AbstractApiClient.java b/vpro-shared-client-resteasy/src/main/java/nl/vpro/api/client/resteasy/AbstractApiClient.java index eb29da881..8c1ae257a 100644 --- a/vpro-shared-client-resteasy/src/main/java/nl/vpro/api/client/resteasy/AbstractApiClient.java +++ b/vpro-shared-client-resteasy/src/main/java/nl/vpro/api/client/resteasy/AbstractApiClient.java @@ -37,22 +37,31 @@ import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.client.*; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHeaderElementIterator; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; -import org.jboss.resteasy.client.jaxrs.*; +import org.jboss.resteasy.client.jaxrs.ClientHttpEngine; +import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; +import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget; import org.jboss.resteasy.client.jaxrs.cache.BrowserCache; import org.jboss.resteasy.client.jaxrs.cache.BrowserCacheFeature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import nl.vpro.jackson2.Jackson2Mapper; -import nl.vpro.jmx.*; +import nl.vpro.jmx.CountAspect; +import nl.vpro.jmx.Counter; +import nl.vpro.jmx.MBeans; import nl.vpro.rs.client.*; -import nl.vpro.util.*; +import nl.vpro.util.LeaveDefaultsProxyHandler; +import nl.vpro.util.ThreadPools; +import nl.vpro.util.TimeUtils; +import nl.vpro.util.XTrustProvider; /** * @author Roelof Jan Koekoek @@ -85,7 +94,10 @@ public abstract class AbstractApiClient implements AbstractApiClientMXBean, Auto protected Integer maxConnectionsNoTimeout; protected Integer maxConnectionsPerRouteNoTimeout; + protected Duration connectionInPoolTTL; + protected Duration validateAfterInactivity; + protected final Map counter = new HashMap<>(); protected Duration countWindow = Duration.ofHours(24); protected Integer bucketCount = 24; @@ -123,6 +135,7 @@ protected AbstractApiClient( Integer maxConnectionsNoTimeout, Integer maxConnectionsPerRouteNoTimeout, Duration connectionInPoolTTL, + Duration validateAfterInactivity, Duration countWindow, Integer bucketCount, Duration warnThreshold, @@ -145,6 +158,7 @@ protected AbstractApiClient( this.maxConnectionsNoTimeout = maxConnectionsNoTimeout == null ? 3 : maxConnectionsNoTimeout; this.maxConnectionsPerRouteNoTimeout = maxConnectionsPerRouteNoTimeout == null ? 3 : maxConnectionsPerRouteNoTimeout; this.connectionInPoolTTL = connectionInPoolTTL; + this.validateAfterInactivity = validateAfterInactivity; setBaseUrl(baseUrl); this.countWindow = countWindow == null ? this.countWindow : countWindow; this.bucketCount = bucketCount == null ? this.bucketCount : bucketCount; @@ -181,6 +195,7 @@ protected String getVersion(String prop, ClassLoader loader) { } return properties.getProperty(prop); } + public static String getUserAgent(final String name, final String version) { final String javaVersion = System.getProperty("java.version"); return String.format("%s/%s (Java/%s)", name, version, javaVersion); @@ -343,8 +358,9 @@ private CloseableHttpClient getHttpClient( Duration connectTimeout, Duration socketTimeout, Integer maxConnections, - Integer maxConnectionsPerRoute, - Duration connectionInPoolTTL) { + Integer maxConnectionsPerRoute, + Duration connectionInPoolTTL, + Duration validateAfterInactivity) { SocketConfig socketConfig = SocketConfig.custom() .setTcpNoDelay(true) .setSoKeepAlive(true) @@ -358,8 +374,11 @@ private CloseableHttpClient getHttpClient( if (maxConnectionsPerRoute == null) { maxConnectionsPerRoute = 0; } + // Why is connectionInPoolTTL the criterion to check? if (connectionInPoolTTL != null) { connectionManager = new PoolingHttpClientConnectionManager(connectionInPoolTTL.toMillis(), TimeUnit.MILLISECONDS); + connectionManager.setValidateAfterInactivity((int) validateAfterInactivity.toMillis()); + if (maxConnections > 0) { connectionManager.setMaxTotal(maxConnections); } @@ -418,7 +437,7 @@ private CloseableHttpClient getHttpClient( public synchronized ClientHttpEngine getClientHttpEngine() { if (clientHttpEngine == null) { - clientHttpEngine = ResteasyHelper.createApacheHttpClient(getHttpClient(connectionRequestTimeout, connectTimeout, socketTimeout, maxConnections, maxConnectionsPerRoute, connectionInPoolTTL), false); + clientHttpEngine = ResteasyHelper.createApacheHttpClient(getHttpClient(connectionRequestTimeout, connectTimeout, socketTimeout, maxConnections, maxConnectionsPerRoute, connectionInPoolTTL, validateAfterInactivity), false); } return clientHttpEngine; @@ -426,7 +445,7 @@ public synchronized ClientHttpEngine getClientHttpEngine() { public synchronized ClientHttpEngine getClientHttpEngineNoTimeout() { if (clientHttpEngineNoTimeout == null) { - clientHttpEngineNoTimeout = ResteasyHelper.createApacheHttpClient(getHttpClient(connectionRequestTimeout, connectTimeout, null, maxConnectionsNoTimeout, maxConnectionsPerRouteNoTimeout, null), false); + clientHttpEngineNoTimeout = ResteasyHelper.createApacheHttpClient(getHttpClient(connectionRequestTimeout, connectTimeout, null, maxConnectionsNoTimeout, maxConnectionsPerRouteNoTimeout, null, validateAfterInactivity), false); } return clientHttpEngineNoTimeout; } @@ -490,7 +509,7 @@ public Duration getConnectionInPoolTTL() { } public void setConnectionInPoolTTL(Duration connectionInPoolTTL) { - if (! Objects.equals(this.connectionInPoolTTL, connectionInPoolTTL)) { + if (!Objects.equals(this.connectionInPoolTTL, connectionInPoolTTL)) { this.connectionInPoolTTL = connectionInPoolTTL; clientHttpEngine = null; invalidate(); @@ -501,6 +520,7 @@ public void setConnectionInPoolTTL(Duration connectionInPoolTTL) { public String getCountWindowString() { return countWindow.toString(); } + @Override public void setCountWindowString(String countWindow) { Duration toSet = TimeUtils.parseDuration(countWindow).orElse(Duration.ofSeconds(30)); @@ -708,7 +728,7 @@ protected ResteasyClientBuilder defaultResteasyClientBuilder(ClientHttpEngine en * For further building the client you can override this method. * If you need more control you can also use the several 'buildFurther' arguments. */ - protected void buildResteasy(ResteasyClientBuilder builder) { + protected void buildResteasy(ResteasyClientBuilder builder) { }