HTTPClient 连接池
向Dirud集群写入数据时,采用HTTPClient向集群提交数据,由于数据量大,需要以多线程方式开启多个线程,单个的HTTPClient会出现连接超时,效率低的情况。高并发的情况下,提高HTTP的请求效率,可以使用HTTPClient连接池的方式,减少3次握手的次数。
maven依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
连接管理器参数设置
private static final int CONNECT_TIMEOUT = 5000; // 建立连接的超时连接
private static final int REQUEST_TIMEOUT = 5000; // 等待连接池返回可用连接的超时时间
private static final int SOCKET_TIMEOUT = 5000; // 服务器读超时时间
private static final int MAX_TOTAL_CONNECTIONS = 8000; // 总超时
private static final int DEFAULT_KEEP_ALIVE_TIME_MILLIS = 20 * 1000; // keep-alive
private static final int CLOSE_IDLE_CONNECTION_WAIT_TIME_SECS = 30; // 空闲连接释放时间(秒)
HTTPClient 连接管理器
PoolingHttpClientConnectionManagerd 是 HttpClient 默认的连接管理器,对连接进行池化管理。从原来的org.apache.http.conn.ssl 包挪到了org.apache.http.ssl 包,基本用法不变。
@Bean
public PoolingHttpClientConnectionManager poolingConnectionManager() {
// 创建服务连接对象
SSLContextBuilder builder = new SSLContextBuilder();
// 连接池管理器初始化
try {
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
} catch (NoSuchAlgorithmException | KeyStoreException e) {
logger.error("Pooling Connection Manager Initialisation failure because of " + e.getMessage(), e);
}
// 客户端验证服务器身份的策略
SSLConnectionSocketFactory sslsf = null;
try {
sslsf = new SSLConnectionSocketFactory(builder.build());
} catch (KeyManagementException | NoSuchAlgorithmException e) {
logger.error("Pooling Connection Manager Initialisation failure because of " + e.getMessage(), e);
}
assert sslsf != null : "SSLConnectionSocketFactory must not = null!";
// 设置协议http和https对应的处理socket链接工厂的对象
// 协议方案
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
.<ConnectionSocketFactory>create()
.register("https", sslsf)
.register("http", new PlainConnectionSocketFactory())
.build();
// 创建已经注册的连接管理器
PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
// 配置持久连接的最大限制,保持在连接池或由连接管理器租用
poolingConnectionManager.setMaxTotal(MAX_TOTAL_CONNECTIONS);
return poolingConnectionManager;
}
HTTPClient 复用持久性连接
- 当有连接第一次使用的时候建立连接
- 结束时对应连接不关闭,归还到池中
- 下次同个目的的连接可从池中获取一个可用连接
定期清理过期连接
@Bean
public ConnectionKeepAliveStrategy connectionKeepAliveStrategy() {
// 根据重用策略判断当前连接是否要复用
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 && "timeout".equalsIgnoreCase(param)) {
return Long.parseLong(value) * 1000;
}
}
return DEFAULT_KEEP_ALIVE_TIME_MILLIS; // 保持连接
};
}
创建HttpClient对象,给httpclient设置连接管理器
一般通过CloseableHttpClient httpClient = HttpClients.custom().build();获取到一个httpClient。HttpClients.custom().build()方法中构造把处理链构造起来。
@Bean
public CloseableHttpClient httpClient() {
// 设置请求的配置
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(REQUEST_TIMEOUT)
.setConnectTimeout(CONNECT_TIMEOUT)
.setSocketTimeout(SOCKET_TIMEOUT).build();
return HttpClients.custom()
.setDefaultRequestConfig(requestConfig) // 请求的配置
.setConnectionManager(poolingConnectionManager()) // 连接池管理器
.setKeepAliveStrategy(connectionKeepAliveStrategy()) // 连接是否复用
.build();
}
还没有评论,来说两句吧...