使用HttpClient时如何完全释放连接?

时间:2018-11-13 16:35:35

标签: java apache-httpclient-4.x connection-leaks

我使用HttpClient(https://hc.apache.org/httpcomponents-client-4.5.x/index.html)来回并行进行许多http调用。运行一段时间后,它会收到以下异常:

java.net.BindException: Address already in use: connect

我试图关闭所有可见的内容,但是我仍然必须错过一些东西,因为它仍然存在该错误。

如何正确释放连接以避免此连接泄漏问题?

下面是重现该问题的测试用例,它在Windows的Java8中运行:

public void test(String url) throws Exception {
    List<Thread> threads = new ArrayList<Thread>();
    for(int t=0; t<40; t++) {
        int tt = t;
        threads.add(new Thread(() -> {
            for(int i=0; i<Integer.MAX_VALUE; i++) {
                URI metadataUri;
                try {
                    metadataUri = new URI(url);
                } catch (Exception e1) {
                    e1.printStackTrace();
                    continue;
                }

                HttpPost httpRequest = new HttpPost(metadataUri);
                httpRequest.setEntity(new ByteArrayEntity( "abc".getBytes()));
                //httpRequest.addHeader("Connection", "close");

                CloseableHttpClient httpclient = HttpClients.custom().build();
                try {
                    CloseableHttpResponse metadataResponse2 = httpclient.execute(httpRequest);
                    metadataResponse2.close();
                } catch (ClientProtocolException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        httpRequest.completed();
                        httpRequest.releaseConnection();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    try {
                        httpclient.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                System.out.println("thread " + tt + " round " + i);
            }
        }));
    }

    for(Thread thread : threads) {
        thread.start();
    }
}

1 个答案:

答案 0 :(得分:0)

通常,尝试使用资源(see reference)应该可以解决此问题:

            try (CloseableHttpClient httpclient = HttpClients.custom().build();
                CloseableHttpResponse metadataResponse2 = httpclient.execute(httpRequest)) {
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                httpRequest.completed();
                httpRequest.releaseConnection();

            }