Apache HttpClient 資源釋放、請求超時,致使線程池用光、內存不足

Apache HttpClient,聽說很強大,能夠支持峯值一秒7萬以上的請求。不過須要注意一些資源釋放和超時處理的問題。json

問題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);
   }
}app

問題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();post

--------------------- 
做者:Clement-Xu 
來源:CSDN 
原文:https://blog.csdn.net/clementad/article/details/75649625?utm_source=copy 
版權聲明:本文爲博主原創文章,轉載請附上博文連接!ui

相關文章
相關標籤/搜索