【发布时间】:2026-01-30 15:20:16
【问题描述】:
我正在访问 Tomcat 8.5 Web 服务器的 Java“客户端”中运行性能测试。在大约 13,000 个请求之后,HTTP 请求失败并出现错误,
org.apache.http.impl.client.DefaultHttpClient tryConnect
INFO: Retrying connect
java.net.BindException: Address already in use: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:127)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:294)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:643)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:479)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
代码是,
for (int i = 0; i < 15000; i++) {
try {
if (i % 1000 == 0) System.out.println("Iterations: " + Integer.toString(i));
HttpGet request = new HttpGet("http://localhost:9080");
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(request, new BasicHttpContext());
HttpEntity entity = response.getEntity();
EntityUtils.consume(entity);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Iterations: " + Integer.toString(i));
System.exit(1);
}
}
如果我缓存 DefaultHttpClient,则不会发生错误。 也试过了,
request.releaseConnection();
client.getConnectionManager().shutdown();
但不会改变错误。 该错误似乎不是由客户端引起的。如果我在 URL 中访问另一个网站,那就没问题了。似乎是由于 Windows 中的 Tomcat 耗尽了文件句柄或套接字资源之类的。 如果我在它崩溃后立即将它作为另一个进程再次运行,它将在 1 次运行中失败,而不是 13,000 次,所以问题是 Tomcat 资源不足。似乎 DefaultHttpClient 没有关闭它的连接,或者 Tomcat 在 gc 发生之前没有释放它的连接。
使用 HTTPClient 4.2.5
任何想法为什么会发生,或者如何解决?
【问题讨论】:
-
该错误是由客户端引起的。你的本地端口用完了,所以一定有连接泄漏。可能不在此代码中。
-
很明显,您应该缓存客户端。它会做连接池,但如果你继续实例化新实例,它就不能。
-
如果问题是客户端用尽了端口,那么如果我使用其他 URL 而不是本地 tomcat,为什么不会发生?似乎它与服务器有关。这是唯一的测试代码,连接泄漏在哪里?
-
DefaultHttpClient 执行请求后是否不释放连接?添加 releaseConnection() 和 getConnectionManager().shutdown() 不会改变行为。
-
您是否尝试过
client.close()或将客户端包装在try-with-resources 中?在我的代码中,我找到了接口CloseableHttpClient和CloseableHttpResponse,它们都通过try-with-resources 关闭。
标签: java apache-commons-httpclient