Apache HttpClient,据说很强大,可以支持峰值一秒7万以上的请求。不过需要注意一些资源释放和超时处理的问题。
问题1:线程资源无法释放,最终导致内存不足、或线程池被用光。
问题代码:
private static HttpClient httpClient = HttpClientBuilder.create().build();
private void sendHttpPost(String httpUrl, Object body) {
try {
HttpPost request = new HttpPost(httpUrl);
StringEntity params = new StringEntity(new ObjectMapper().writeValueAsString(body), "UTF-8");
request.addHeader("content-type", "application/json");
request.setEntity(params);
httpClient.execute(request); //问题代码
} catch (Exception ex) {
logger.error("Http post error. body={}", body, ex);
}
}
原因:httpClient.execute()执行的返回值response没有被close,导致线程一直在等待。
解决:改用CloseableHttpClient,并保证httpClient.execute()执行的response最终被close掉。而httpClient无需close,可以重复使用。
改正后的代码:
//private static HttpClient httpClient = HttpClientBuilder.create().build();
private static CloseableHttpClient httpClient = HttpClientBuilder.create().build();
private void sendHttpPost(String httpUrl, Object body) {
try {
HttpPost request = new HttpPost(httpUrl);
StringEntity params = new StringEntity(new ObjectMapper().writeValueAsString(body), "UTF-8");
request.addHeader("content-type", "application/json");
request.setEntity(params);
//httpClient.execute(request);
try (CloseableHttpResponse response = httpClient.execute(request)) { //response.close()会被自动调用
//result = this.extractResultInfo(response);
}catch (Exception ex) {
logger.error("Http post execute error. body={}", body, ex);
}
} catch (Exception ex) {
logger.error("Http post error. body={}", body, ex);
}
}
问题2:如果使用HttpClient访问外部url,有时候会出现连接超时或应答超时的情况。如果没有超时处理,也会导致内存不足、或线程池被用光。
问题代码:如上。
解决:创建httpClient时,设置几个timeout时间:
//private static HttpClient httpClient = HttpClientBuilder.create().build();
private static CloseableHttpClient httpClient;// = HttpClientBuilder.create().build(); //no timeout handling...
static {
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
//客户端和服务器建立连接的timeout
requestConfigBuilder.setConnectTimeout(30000);
//从连接池获取连接的timeout
requestConfigBuilder.setConnectionRequestTimeout(30000);
//连接建立后,request没有回应的timeout
requestConfigBuilder.setSocketTimeout(30000);
HttpClientBuilder clientBuilder = HttpClientBuilder.create();
clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());
clientBuilder.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(30000).build()); //连接建立后,request没有回应的timeout
clientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());
httpClient = clientBuilder.build();
---------------------
作者:Clement-Xu
来源:CSDN
原文:https://blog.csdn.net/clementad/article/details/75649625?utm_source=copy
版权声明:本文为博主原创文章,转载请附上博文链接!