对Apache HttpClient的优化,基于HttpClient4.4+的连接池(PoolingHttpClientConnectionManager),结合RestTemplate 使其在高QPS,并发请求下提高效率。
HttpClient优化点
- httpclient是一个线程安全的类,全局维护一个可避免httpclient反复创建带来的开销。
- 使用PoolingHttpClientConnectionManager连接池避免反复创建tcp连接
- 定时监控清理关闭服务端已CLOSE的连接
- 合理配置连接池的总连接数与并发数
HttpClient与RestTemplate实现
- 配置PoolingHttpClientConnectionManager连接池
public static CloseableHttpClient getCloseableHttpClient(boolean isRetry) {
// 长连接保持30秒
PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(30, TimeUnit.SECONDS);
// 总连接数
pollingConnectionManager.setMaxTotal(200);
// 默认同路由的并发数
pollingConnectionManager.setDefaultMaxPerRoute(100);
HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setConnectionManager(pollingConnectionManager);
// 重试次数,默认是3次,设置为2次,没有开启
if (isRetry) {
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(2, true));
} else {
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false));
}
// 保持长连接配置,需要在头添加Keep-Alive
httpClientBuilder.setKeepAliveStrategy(DefaultConnectionKeepAliveStrategy.INSTANCE);
CloseableHttpClient httpClient = httpClientBuilder.build();
runIdleConnectionMonitor(pollingConnectionManager);
return httpClient;
}
- 自定义keepAliveStrategy
private static ConnectionKeepAliveStrategy getConnectionKeepAliveStrategy(){
return (response, 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 60 * 1000;//如果没有约定,则默认定义时长为60s
};
}
- 定时监控清理实现连接关闭
private static void runIdleConnectionMonitor(HttpClientConnectionManager clientConnectionManager) {
FixedRateSchedule schedule = new FixedRateScheduleImpl();
schedule.setPoolTag("IDLE_CONNECTION_MONITOR_POOL");
schedule.init();
schedule.schedule(() -> {
//关闭过期的链接
clientConnectionManager.closeExpiredConnections();
//关闭闲置超过30s的链接
clientConnectionManager.closeIdleConnections(30, TimeUnit.SECONDS);
}, IDLE_INITIALDELAY, IDLE_PERIOD, TimeUnit.MILLISECONDS);
}
- 代码
https://github.com/ChinaLHR/HttpClientOptimization