HttpClient 连接池关闭

idi*_*ous 5 java apache-httpcomponents apache-httpclient-4.x

我正在使用 HttpClient v4.5.5

我有一个HttpClient如下:

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

然后我使用 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;
}
Run Code Online (Sandbox Code Playgroud)

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

偶尔我会收到一个错误

java.lang.IllegalStateException: Connection pool shut down从我读到的内容来看,无论是在较旧的 HttpClient 版本中还是在您关闭 HttpClient 时都会发生这种情况。我不这样做。所以我不明白为什么我会收到这个错误。它会恢复,但有这样的例外是一个问题。

小智 2

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

try (PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager()) {
                manager.setMaxTotal(600);
                manager.setDefaultMaxPerRoute(100);
Run Code Online (Sandbox Code Playgroud)

此构造将自动关闭资源。

类:PoolingHttpClientConnectionManager 存在如下方法:

 public void close() {
        this.shutdown();
    }
Run Code Online (Sandbox Code Playgroud)

最后将调用 close()。