2017-12-28 7 views
1

httpclients 4.5.4를 사용하는 동안 문제가 발생했습니다. 연결과 관련된 모든 것을 닫으면 Java GC에서 PoolingHttpClientConnectionManager 개체를 수집 할 수 없습니다. 약 1 개월 동안 응용 프로그램이 실행되므로 OOM 예외가 발생합니다. 내 코드는 https://hc.apache.org/httpcomponents-client-4.5.x/httpclient/examples/org/apache/http/examples/client/ClientConnectionRelease.java의 예와 같습니다. InternalHttpClient 객체는 Java GC로도 수집 할 수 없습니다. 아래 코드에는 두 클래스에 대한 참조가 들어있는 객체가 있습니까?httpclient4.5.4에서 PoolingHttpClientConnectionManager를 해제하는 방법

import java.io.BufferedReader; 
    import java.io.File; 
    import java.io.InputStream; 
    import java.io.InputStreamReader; 
    import java.util.Map; 

    import org.apache.http.HttpStatus; 
    import org.apache.http.client.methods.CloseableHttpResponse; 
    import org.apache.http.client.methods.HttpPost; 
    import org.apache.http.entity.ContentType; 
    import org.apache.http.entity.mime.MultipartEntityBuilder; 
    import org.apache.http.entity.mime.content.FileBody; 
    import org.apache.http.entity.mime.content.StringBody; 
    import org.apache.http.impl.client.CloseableHttpClient; 
    import org.apache.http.impl.client.HttpClients; 
    import org.slf4j.Logger; 
    import org.slf4j.LoggerFactory; 

    public class HttpUtil { 

     private static Logger logger = LoggerFactory.getLogger(HttpUtil.class); 

     /** 
     * Http post请求 
     */ 
     public static String doHttpPost(String postUrl, Map<String, String> headers, 
       Map<String,String> params,String filePath) { 
      try { 
       CloseableHttpClient httpClient = HttpClients.createDefault(); 
       try { 
        HttpPost post = getHttpPost(postUrl, headers, params, filePath); 
        CloseableHttpResponse response = httpClient.execute(post); 
        try { 
         InputStream inputStream = null; 
         InputStreamReader inputStreamReader = null; 
         BufferedReader bufferedReader = null; 
         if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 
          try { 
           inputStream = response.getEntity().getContent(); 
           inputStreamReader = new InputStreamReader(inputStream); 
           bufferedReader = new BufferedReader(inputStreamReader); 
           return bufferedReader.readLine(); 
          }catch (Exception e) { 
           logger.warn("do http post fail : ", e); 
          }finally { 
           if (bufferedReader != null) { 
            logger.info("release bufferedReader: " + filePath); 
            bufferedReader.close(); 
           } 
           if (inputStreamReader != null) { 
            logger.info("release inputStreamReader: " +filePath); 
            inputStreamReader.close(); 
           } 
           if (inputStream != null) { 
            logger.info("release inputStream: " +filePath); 
            inputStream.close(); 
           } 
          } 
         } 
        } catch (Exception e) { 
         logger.warn("do http post fail: ", e); 
        } finally { 
         if (response != null) { 
          logger.info("release response: " + filePath); 
          response.close(); 
         } 
         if (post != null) { 
          logger.info("release HttpPost: " + filePath); 
          post.releaseConnection(); 
         } 
        } 
       } catch (Exception e) { 
        logger.warn("do http post fail: ", e); 
       } finally { 
        if (httpClient != null) { 
         logger.info("release httpClient: " + filePath); 
         httpClient.close(); 
         logger.info("release connectionManager: " + filePath); 
         httpClient.getConnectionManager().shutdown(); 
        } 
       } 
      } catch (Exception e) { 
       logger.warn("do http post fail: ", e); 
      } 

      return ""; 
     } 

     private static HttpPost getHttpPost(String postUrl, Map<String, String> headers, 
       Map<String, String> params, String filePath) { 
      HttpPost post = new HttpPost(postUrl); 
      String[] headerKeys = headers.keySet().toArray(new String[headers.keySet().size()]); 
      for (String key : headerKeys) { 
       post.setHeader(key, headers.get(key)); 
      } 

      FileBody fileBody = new FileBody(new File(filePath)); 
      MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); 
      multipartEntityBuilder.addPart("express_image", fileBody); 

      String[] paramKeys = params.keySet().toArray(new String[params.keySet().size()]); 
      for (String key : paramKeys) { 
       StringBody valueBody = new StringBody(params.get(key), ContentType.TEXT_PLAIN); 
       multipartEntityBuilder.addPart(key, valueBody); 
      } 

      post.setEntity(multipartEntityBuilder.build()); 
      return post; 
     } 

    } 
+0

답변을 얻었습니다. 또 다른 클래스는 PoolingHttpClientConnectionManager를 사용하고 풀어주지 않았습니다. 나는 매트 메모리 맵 분석에서 그들을 발견했다. 모두 감사합니다. –

답변

0

당신은 메모리가 부족 내가 왜 당신을 말할 수는 없지만, (당신은 "권장되는 방법"을 사용에도 불구하고) 나는 그것을이 방법을 수행하는 더 좋은 생각이 없다, 당신을 알 수 있습니다.

버전 4.5.3에서 CloseableHttpClientPoolingHttpClientConnectionManager을 사용하고 있습니다. 둘 다 싱글 톤으로 할당되어 모든 요청에 ​​사용됩니다. 내 응용 프로그램은 현재 한 달이 초당 약 하나의 요청을 처리하고 있기 때문에 현재 실행되고 있습니다 (별로 많지 않음).

각 연결마다 새 클라이언트를 만드는 것이 각 여행에 대해 새 차를 구입하는 것보다 효율적이라는 점에 유의하십시오.

관련 문제