diff options
author | Vitaly Takmazov | 2021-04-12 22:00:11 +0300 |
---|---|---|
committer | Vitaly Takmazov | 2021-04-12 22:00:11 +0300 |
commit | 3e65b5eeaee89758558667787e48a5ab9908a46f (patch) | |
tree | bd4898a257706097996b0fcb0d83c7930e291c12 /src/main/java/com/juick/config/HttpClientConfig.java | |
parent | 43963103bdacecd6943660baa8e4c5b21a490219 (diff) |
ActivityPub: pooling HTTP client
Diffstat (limited to 'src/main/java/com/juick/config/HttpClientConfig.java')
-rw-r--r-- | src/main/java/com/juick/config/HttpClientConfig.java | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/src/main/java/com/juick/config/HttpClientConfig.java b/src/main/java/com/juick/config/HttpClientConfig.java new file mode 100644 index 00000000..0b23ca15 --- /dev/null +++ b/src/main/java/com/juick/config/HttpClientConfig.java @@ -0,0 +1,111 @@ +package com.juick.config; + +import java.util.concurrent.TimeUnit; + +import org.apache.http.HeaderElement; +import org.apache.http.HeaderElementIterator; +import org.apache.http.HttpResponse; +import org.apache.http.client.config.CookieSpecs; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.conn.ConnectionKeepAliveStrategy; + +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.message.BasicHeaderElementIterator; +import org.apache.http.protocol.HTTP; +import org.apache.http.protocol.HttpContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; + +/** + * - Uses a connection pool to re-use connections and save overhead of creating connections. + * - Has a custom connection keep-alive strategy (to apply a default keep-alive if one isn't specified) + * - Starts an idle connection monitor to continuously clean up stale connections. + */ +@Configuration +public class HttpClientConfig { + + private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientConfig.class); + + // Determines the timeout in milliseconds until a connection is established. + private static final int CONNECT_TIMEOUT = 30000; + + // The timeout when requesting a connection from the connection manager. + private static final int REQUEST_TIMEOUT = 30000; + + // The timeout for waiting for data + private static final int SOCKET_TIMEOUT = 60000; + + private static final int MAX_TOTAL_CONNECTIONS = 50; + private static final int DEFAULT_KEEP_ALIVE_TIME_MILLIS = 20 * 1000; + private static final int CLOSE_IDLE_CONNECTION_WAIT_TIME_SECS = 30; + + @Bean + public PoolingHttpClientConnectionManager poolingConnectionManager() { + PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager(); + poolingConnectionManager.setMaxTotal(MAX_TOTAL_CONNECTIONS); + return poolingConnectionManager; + } + + @Bean + public ConnectionKeepAliveStrategy connectionKeepAliveStrategy() { + return new ConnectionKeepAliveStrategy() { + @Override + public long getKeepAliveDuration(HttpResponse response, HttpContext context) { + HeaderElementIterator it = new BasicHeaderElementIterator + (response.headerIterator(HTTP.CONN_KEEP_ALIVE)); + while (it.hasNext()) { + HeaderElement he = it.nextElement(); + String param = he.getName(); + String value = he.getValue(); + + if (value != null && param.equalsIgnoreCase("timeout")) { + return Long.parseLong(value) * 1000; + } + } + return DEFAULT_KEEP_ALIVE_TIME_MILLIS; + } + }; + } + + @Bean + public CloseableHttpClient httpClient() { + RequestConfig requestConfig = RequestConfig.custom() + .setCookieSpec(CookieSpecs.IGNORE_COOKIES) + .setConnectionRequestTimeout(REQUEST_TIMEOUT) + .setConnectTimeout(CONNECT_TIMEOUT) + .setSocketTimeout(SOCKET_TIMEOUT).build(); + + return HttpClients.custom() + .setDefaultRequestConfig(requestConfig) + .setConnectionManager(poolingConnectionManager()) + .setKeepAliveStrategy(connectionKeepAliveStrategy()) + .build(); + } + + @Bean + public Runnable idleConnectionMonitor(final PoolingHttpClientConnectionManager connectionManager) { + return new Runnable() { + @Override + @Scheduled(fixedDelay = 10000) + public void run() { + try { + if (connectionManager != null) { + LOGGER.trace("run IdleConnectionMonitor - Closing expired and idle connections..."); + connectionManager.closeExpiredConnections(); + connectionManager.closeIdleConnections(CLOSE_IDLE_CONNECTION_WAIT_TIME_SECS, TimeUnit.SECONDS); + } else { + LOGGER.trace("run IdleConnectionMonitor - Http Client Connection manager is not initialised"); + } + } catch (Exception e) { + LOGGER.error("run IdleConnectionMonitor - Exception occurred. msg={}, e={}", e.getMessage(), e); + } + } + }; + } +}
\ No newline at end of file |