Apache HttpClient 资源释放、请求超时,导致线程池用光、内存不足

Apache HttpClient,据说很强大,可以支持峰值一秒7万以上的请求。不过需要注意一些资源释放和超时处理的问题。

问题1:线程资源无法释放,最终导致内存不足、或线程池被用光。
问题代码:
[java] view plain copy
  1. private static HttpClient httpClient = HttpClientBuilder.create().build();  
  2. private void sendHttpPost(String httpUrl, Object body) {  
  3.    try {  
  4.       HttpPost request = new HttpPost(httpUrl);  
  5.       StringEntity params = new StringEntity(new ObjectMapper().writeValueAsString(body), "UTF-8");  
  6.       request.addHeader("content-type""application/json");  
  7.       request.setEntity(params);  
  8.       httpClient.execute(request); //问题代码  
  9.    } catch (Exception ex) {  
  10.       logger.error("Http post error. body={}", body, ex);  
  11.    }  
  12. }  

原因:httpClient.execute()执行的返回值response没有被close,导致线程一直在等待。
解决:改用CloseableHttpClient,并保证httpClient.execute()执行的response最终被close掉。而httpClient无需close,可以重复使用。
改正后的代码:
[java] view plain copy
  1. //private static HttpClient httpClient = HttpClientBuilder.create().build();  
  2. private static CloseableHttpClient httpClient = HttpClientBuilder.create().build();  
  3. private void sendHttpPost(String httpUrl, Object body) {  
  4.    try {  
  5.       HttpPost request = new HttpPost(httpUrl);  
  6.       StringEntity params = new StringEntity(new ObjectMapper().writeValueAsString(body), "UTF-8");  
  7.       request.addHeader("content-type""application/json");  
  8.       request.setEntity(params);  
  9.       //httpClient.execute(request);  
  10.       try (CloseableHttpResponse response = httpClient.execute(request)) { //response.close()会被自动调用  
  11.          //result = this.extractResultInfo(response);  
  12.       }catch (Exception ex) {  
  13.          logger.error("Http post execute error. body={}", body, ex);  
  14.       }  
  15.    } catch (Exception ex) {  
  16.       logger.error("Http post error. body={}", body, ex);  
  17.    }  
  18. }  

问题2:如果使用HttpClient访问外部url,有时候会出现连接超时或应答超时的情况。如果没有超时处理,也会导致内存不足、或线程池被用光。
问题代码:如上。
解决:创建httpClient时,设置几个timeout时间:
[java] view plain copy
  1. //private static HttpClient httpClient = HttpClientBuilder.create().build();  
  2. private static CloseableHttpClient httpClient;// = HttpClientBuilder.create().build(); //no timeout handling...  
  3.   
  4. static {  
  5.    RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();  
  6.    //客户端和服务器建立连接的timeout  
  7.    requestConfigBuilder.setConnectTimeout(30000);  
  8.    //从连接池获取连接的timeout  
  9.    requestConfigBuilder.setConnectionRequestTimeout(30000);  
  10.    //连接建立后,request没有回应的timeout  
  11.    requestConfigBuilder.setSocketTimeout(30000);  
  12.   
  13.    HttpClientBuilder clientBuilder = HttpClientBuilder.create();  
  14.    clientBuilder.setDefaultRequestConfig(requestConfigBuilder.build());  
  15.    clientBuilder.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(30000).build()); //连接建立后,request没有回应的timeout  
  16.    clientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());  
  17.    httpClient = clientBuilder.build();  
  18. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值