我正在将PoolingHttpClientConnectionManager添加到我们的Spring Boot服务中,该服务目前正在使用RestTemplate和CloseableHttpClient发出请求。该服务使用Apache http组件4.5。
如果出现临时网络中断会发生什么?坏连接会从池中被丢弃吗?或者在中断期间池会被坏连接填满吗?一旦中断结束,池会自行恢复吗?还是需要编写代码来检测它们并将它们从池中删除?
这是我到目前为止的代码:
@Bean
public CloseableHttpClient closeableHttpClient() {
CloseableHttpClient client = HttpClients.custom()
.setDefaultRequestConfig(getDefaultRequestConfig())
.setConnectionManager(poolingHttpClientConnectionManager())
.setKeepAliveStrategy(getConnectionKeepAliveStrategy())
.setRetryHandler(getHttpRequestRetryHandler())
.build();
return client;
}
@Bean
public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() {
Registry<ConnectionSocketFactory> socketFactoryRegistry = getSocketFactoryRegistry();
PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
poolingConnectionManager.setMaxTotal(maxTotalConnections);
poolingConnectionManager.setDefaultMaxPerRoute(maxRouteConnections);
return poolingConnectionManager;
}
@Bean
public Runnable idleConnectionMonitor(PoolingHttpClientConnectionManager pool) {
return new Runnable() {
@Override
@Scheduled(fixedDelay = 20000)
public void run() {
if (pool != null) {
pool.closeExpiredConnections();
pool.closeIdleConnections(idleConnectionCloseTime, TimeUnit.MILLISECONDS);
}
}
};
}
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix("idleMonitor");
scheduler.setPoolSize(idleMonitorPoolSize);
return scheduler;
}
private RequestConfig getDefaultRequestConfig() {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(establishConnectionTimeout)
.setConnectionRequestTimeout(fetchConnectionTimeout)
.setSocketTimeout(socketInactivityTimeout)
.build();
return requestConfig;
}
private Registry<ConnectionSocketFactory> getSocketFactoryRegistry() {
SSLConnectionSocketFactory socketFactory;
socketFactory = new SSLConnectionSocketFactory(getSSLContext(), new String[] { sslProtocol }, null, new DefaultHostnameVerifier());
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
.<ConnectionSocketFactory> create().register("https", socketFactory)
.build();
return socketFactoryRegistry;
}
private SSLContext getSSLContext() {
TrustStrategy acceptingTrustStrategy = null;
try {
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(new FileInputStream(new File(keyStoreFile)), keyStorePwd.toCharArray());
return new SSLContextBuilder()
.loadTrustMaterial(keyStore, acceptingTrustStrategy)
.loadKeyMaterial(keyStore, keyStorePwd.toCharArray())
.build();
} catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException | UnrecoverableKeyException e) {
throw new RuntimeException(e);
}
}
private ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy() {
return (httpResponse, httpContext) -> {
HeaderIterator headerIterator = httpResponse.headerIterator(HTTP.CONN_KEEP_ALIVE);
HeaderElementIterator elementIterator = new BasicHeaderElementIterator(headerIterator);
while (elementIterator.hasNext()) {
HeaderElement element = elementIterator.nextElement();
String param = element.getName();
String value = element.getValue();
if (value != null && param.equalsIgnoreCase("timeout")) {
return Long.parseLong(value) * 1000; // convert to ms
}
}
return defaultKeepAliveTime;
};
}
private DefaultHttpRequestRetryHandler getHttpRequestRetryHandler() {
return new DefaultHttpRequestRetryHandler(httprequestRetryCount, false);
}
这些连接变得无效或“陈旧”。如果HttpClient已配置为在使用连接执行请求之前验证连接,则将检测到陈旧的连接并丢弃。