httpclient4.5.4使用默认方式创建连接资源无法释放的问题

rockAman 发布于 2017/12/28 15:42
阅读 384
收藏 1

hi,

求教一个问题,本人最近刚把httpclient版本升级到4.5.4,项目中有个需要用到http post请求发送文件的地方,发现参照这个官方链接https://hc.apache.org/httpcomponents-client-4.5.x/httpclient/examples/org/apache/http/examples/client/ClientConnectionRelease.java 的代码,写了一个工具类,感觉该释放的资源都释放了,但是项目在生产运行了一段时间之后,看内存dump,有大量的

PoolingHttpClientConnectionManager

对象没有被回收。代码如下:

package com.best.oasis.ocr.util;

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;
    }

}

ClosableHttpClient和其对应的连接管理器都已经显式释放了,但是项目跑大概一个多月之后,内存中有大量的InternalHttpClient和PoolingHttpClientConnectionManager对象,导致OOM.

请大神帮忙解答下,谢谢了。

加载中
0
r
rockAman

找到原因了,aliyun的oss也依赖了httpclient,OSSClient没有shutdown,通过mat的对象依赖关系找到的。

a
adam1982
你的ossclient是每次都new的吗?还是一个static的模式?我们项目你的效果差不多,也是大量的pm的对象
返回顶部
顶部