【问题标题】:HttpClient Connection pool shut downHttpClient 连接池关闭
【发布时间】:2018-02-08 12:42:25
【问题描述】:

我正在使用 HttpClient v4.5.5

我有一个HttpClient,如下:

PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
    connManager.setMaxTotal(totalMaxConnections);
    connManager.setDefaultMaxPerRoute(defaultMaxConnPerRoute);
CloseableHttpClient httpClient =HttpClients.custom().setConnectionManager(connManager).setConnectionManagerShared(true).build();

然后我使用http客户端如下:

protected Response connect(final Function<AbstractHttpAdapter, CloseableHttpResponse> pcAction) {
    Response response = null;
    final Instant begin = Instant.now();
    try {
        final CloseableHttpResponse closableResp = pcAction.apply(this);
        try {
            final Instant end = Instant.now();
            if (closableResp != null) {
                final HttpEntity responseEntity = closableResp.getEntity();
                if (responseEntity != null) {
                    response = new Response();
                    InputStream is = responseEntity.getContent();
                    try {

                        final ContentType contentType = ContentType.getOrDefault(responseEntity);
                        Charset charset = contentType.getCharset();
                        if (charset == null)
                            charset = Charset.forName("UTF-8");
                        response.responseText = IOUtils.toString(is, charset.toString());
                        if (closableResp.getStatusLine() != null) {
                            response.statusLine = closableResp.getStatusLine();

                        }
                        Map<String, String> responseHeaders = new HashMap<>();
                        Header[] headers = closableResp.getAllHeaders();
                        for (Header h : headers) {
                            responseHeaders.put(h.getName(), h.getValue());
                        }
                        response.responseHeaders = responseHeaders;
                        response.responseDuration = Duration.between(begin, end).toMillis();
                    } catch (UnsupportedOperationException | IOException e) {
                        LOGGER.error("IO Error: [{}]", e.getMessage());
                        LOGGER.debug("IO Error: {}", e);
                        return null;
                    } finally {
                        is.close();
                    }
                }
            } else {
                LOGGER.debug("NULL CloseableHttpResponse!");
            }
        } finally {
            if (closableResp != null)
                closableResp.close();
        }
    } catch (IOException e) {
        LOGGER.error("IO Error: [{}]", e.getMessage());
        LOGGER.debug("IO Error: {}", e);
        response = null;
    } catch (Exception ex) {
        LOGGER.error("IO Error: [{}]", ex.getMessage());
        LOGGER.debug("IO Error: {}", ex);
        response = null;
    }
    return response;
}

public CloseableHttpResponse executePost(final URL url, final String request, final int connectTimeout,
        final int readTimeout, Map<String, String> extraHeaders) {

    LOGGER.trace("Executing post request...");
    CloseableHttpResponse closeableHttpResponse = null;
    final RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
    final RequestConfig requestConfig = requestConfigBuilder.setSocketTimeout(readTimeout)
            .setConnectTimeout(connectTimeout).build();

    final URI uri = prepareUri(url, null);
    final HttpPost httpPost = new HttpPost(uri);
    try {
        httpPost.setEntity(new StringEntity(request, StandardCharsets.UTF_8));
        httpPost.setConfig(requestConfig);
        if (MapUtils.isNotEmpty(extraHeaders)) {
            for (Map.Entry<String, String> header : extraHeaders.entrySet()) {
                httpPost.setHeader(header.getKey(), header.getValue());
            }
        }
        closeableHttpResponse = httpClient.execute(httpPost, HttpClientContext.create());
    } catch (ClientProtocolException e) {
        LOGGER.error("HTTP Error for URL [{}] and RequestParams [{}]: {}", url, request, e);
    } catch (IOException e) {
        LOGGER.error("IO Error for URL [{}] and RequestParams [{}]: {}", url, request, e.getMessage());
        LOGGER.debug("IO Error for URL [{}] and RequestParams [{}]: {}", url, request, e);
    } catch (Exception e) {
        LOGGER.error("General Error for URL [{}] and RequestParams [{}]: {}", url, request, e);
    }
    return closeableHttpResponse;
}

定期(每隔几分钟)通过threadPoolTaskScheduler 调用connect

偶尔会出错

java.lang.IllegalStateException: Connection pool shut down 并且根据我所阅读的内容,这发生在较旧的 HttpClient 版本或关闭 HttpClient 时。我不这样做。所以我不明白为什么我会收到这个错误。它恢复了,但出现这样的异常是个问题。

【问题讨论】:

  • executePost 方法,我觉得也需要关闭响应

标签: java apache-httpclient-4.x apache-httpcomponents


【解决方案1】:

遇到同样的错误,但最终解决了。 这个错误导致我使用 try () {} 如下:

try (PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager()) {
                manager.setMaxTotal(600);
                manager.setDefaultMaxPerRoute(100);

这个构造会自动关闭资源。

class:PoolingHttpClientConnectionManager 存在如下方法:

 public void close() {
        this.shutdown();
    }

最终会调用 close()。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-23
    • 2018-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-04
    相关资源
    最近更新 更多