Skip to content

Commit 54795d3

Browse files
committed
Added a monitor thread for the PoolingHttpClientConnectionManager that evicts idle no-cert client connections: https://hc.apache.org/httpcomponents-client-4.5.x/current/tutorial/html/connmgmt.html#d5e418
1 parent f10b5da commit 54795d3

File tree

1 file changed

+28
-11
lines changed

1 file changed

+28
-11
lines changed

src/main/java/com/atomgraph/linkeddatahub/Application.java

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
import com.atomgraph.spinrdf.vocabulary.SP;
172172
import com.github.jsonldjava.core.DocumentLoader;
173173
import com.github.jsonldjava.core.JsonLdOptions;
174+
import jakarta.inject.Inject;
174175
import java.io.FileOutputStream;
175176
import java.io.UnsupportedEncodingException;
176177
import java.nio.charset.StandardCharsets;
@@ -192,6 +193,7 @@
192193
import jakarta.ws.rs.client.Client;
193194
import jakarta.ws.rs.client.ClientBuilder;
194195
import jakarta.ws.rs.client.ClientRequestFilter;
196+
import java.util.concurrent.ScheduledExecutorService;
195197
import javax.xml.transform.TransformerException;
196198
import javax.xml.transform.stream.StreamSource;
197199
import net.jodah.expiringmap.ExpiringMap;
@@ -230,7 +232,6 @@
230232
import org.glassfish.hk2.utilities.binding.AbstractBinder;
231233
import org.glassfish.jersey.client.ClientConfig;
232234
import org.glassfish.jersey.apache.connector.ApacheClientProperties;
233-
import org.glassfish.jersey.apache.connector.ApacheConnectionClosingStrategy;
234235
import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
235236
import org.glassfish.jersey.client.ClientProperties;
236237
import org.glassfish.jersey.client.RequestEntityProcessing;
@@ -251,6 +252,7 @@ public class Application extends ResourceConfig
251252

252253
private static final Logger log = LoggerFactory.getLogger(Application.class);
253254

255+
private @Inject ScheduledExecutorService idleConnectionMonitor;
254256
private final ExecutorService importThreadPool;
255257
private final ServletConfig servletConfig;
256258
private final EventBus eventBus = new EventBus();
@@ -623,10 +625,10 @@ public Application(final ServletConfig servletConfig, final MediaTypes mediaType
623625
trustStore = KeyStore.getInstance("JKS");
624626
trustStore.load(new FileInputStream(new java.io.File(new URI(clientTrustStoreURIString))), clientTrustStorePassword.toCharArray());
625627

626-
client = getClient(keyStore, clientKeyStorePassword, trustStore, maxConnPerRoute, maxTotalConn, null, false);
627-
externalClient = getClient(keyStore, clientKeyStorePassword, trustStore, maxConnPerRoute, maxTotalConn, null, false);
628-
importClient = getClient(keyStore, clientKeyStorePassword, trustStore, maxConnPerRoute, maxTotalConn, importKeepAliveStrategy, true);
629-
noCertClient = getNoCertClient(trustStore, maxConnPerRoute, maxTotalConn);
628+
client = createClient(keyStore, clientKeyStorePassword, trustStore, maxConnPerRoute, maxTotalConn, null, false);
629+
externalClient = createClient(keyStore, clientKeyStorePassword, trustStore, maxConnPerRoute, maxTotalConn, null, false);
630+
importClient = createClient(keyStore, clientKeyStorePassword, trustStore, maxConnPerRoute, maxTotalConn, importKeepAliveStrategy, true);
631+
noCertClient = createNoCertClient(trustStore, maxConnPerRoute, maxTotalConn);
630632

631633
if (maxContentLength != null)
632634
{
@@ -1331,7 +1333,7 @@ public void submitImport(RDFImport rdfImport, com.atomgraph.linkeddatahub.apps.m
13311333
* @throws UnrecoverableKeyException key loading error
13321334
* @throws KeyManagementException key loading error
13331335
*/
1334-
public static Client getClient(KeyStore keyStore, String keyStorePassword, KeyStore trustStore, Integer maxConnPerRoute, Integer maxTotalConn, ConnectionKeepAliveStrategy keepAliveStrategy, boolean buffered) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, KeyManagementException
1336+
public Client createClient(KeyStore keyStore, String keyStorePassword, KeyStore trustStore, Integer maxConnPerRoute, Integer maxTotalConn, ConnectionKeepAliveStrategy keepAliveStrategy, boolean buffered) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, KeyManagementException
13351337
{
13361338
if (keyStore == null) throw new IllegalArgumentException("KeyStore cannot be null");
13371339
if (keyStorePassword == null) throw new IllegalArgumentException("KeyStore password string cannot be null");
@@ -1417,7 +1419,7 @@ public void releaseConnection(final HttpClientConnection managedConn, final Obje
14171419
* @param maxTotalConn max total connections
14181420
* @return client instance
14191421
*/
1420-
public static Client getNoCertClient(KeyStore trustStore, Integer maxConnPerRoute, Integer maxTotalConn)
1422+
public Client createNoCertClient(KeyStore trustStore, Integer maxConnPerRoute, Integer maxTotalConn)
14211423
{
14221424
try
14231425
{
@@ -1465,7 +1467,22 @@ public void releaseConnection(final HttpClientConnection managedConn, final Obje
14651467
if (maxConnPerRoute != null) conman.setDefaultMaxPerRoute(maxConnPerRoute);
14661468
if (maxTotalConn != null) conman.setMaxTotal(maxTotalConn);
14671469
conman.setValidateAfterInactivity(5000); // check connections idle for more than Varnish's idle_timeout which is 5s
1468-
1470+
1471+
Integer idleConnTimeout = 5000;
1472+
// create monitor thread that evicts idle connections: https://hc.apache.org/httpcomponents-client-4.5.x/current/tutorial/html/connmgmt.html#d5e418
1473+
idleConnectionMonitor.scheduleAtFixedRate(() ->
1474+
{
1475+
try
1476+
{
1477+
if (log.isDebugEnabled()) log.debug("Evicting idle HTTP connections (every {} ms)", idleConnTimeout);
1478+
conman.closeIdleConnections(idleConnTimeout, TimeUnit.MILLISECONDS);
1479+
}
1480+
catch (Exception ex)
1481+
{
1482+
if (log.isErrorEnabled()) log.error("Error closing idle connections: {}", ex);
1483+
}
1484+
}, 0, idleConnTimeout, java.util.concurrent.TimeUnit.MILLISECONDS);
1485+
14691486
ClientConfig config = new ClientConfig();
14701487
config.connectorProvider(new ApacheConnectorProvider());
14711488
config.register(MultiPartFeature.class);
@@ -1486,17 +1503,17 @@ public void releaseConnection(final HttpClientConnection managedConn, final Obje
14861503
}
14871504
catch (NoSuchAlgorithmException ex)
14881505
{
1489-
if ( log.isErrorEnabled()) log.error("No such algorithm: {}", ex);
1506+
if (log.isErrorEnabled()) log.error("No such algorithm: {}", ex);
14901507
throw new IllegalStateException(ex);
14911508
}
14921509
catch (KeyStoreException ex)
14931510
{
1494-
if ( log.isErrorEnabled()) log.error("Key store error: {}", ex);
1511+
if (log.isErrorEnabled()) log.error("Key store error: {}", ex);
14951512
throw new IllegalStateException(ex);
14961513
}
14971514
catch (KeyManagementException ex)
14981515
{
1499-
if ( log.isErrorEnabled()) log.error("Key management error: {}", ex);
1516+
if (log.isErrorEnabled()) log.error("Key management error: {}", ex);
15001517
throw new IllegalStateException(ex);
15011518
}
15021519
}

0 commit comments

Comments
 (0)