gpt4 book ai didi

java - Apache DefaultHttpClient - java.net.BindException : Address already in use: connect

转载 作者:行者123 更新时间:2023-12-01 14:09:10 27 4
gpt4 key购买 nike

我正在访问 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

任何想法为什么会发生,或者如何解决?

最佳答案

我无法重现您遇到的相同错误。无论如何,当我在单线程中运行您的示例时,我收到 NoRouteToHostException。

13:37:57.917 [main] DEBUG org.apache.http.impl.conn.BasicClientConnectionManager - Releasing connection org.apache.http.impl.conn.ManagedClientConnectionImpl@2c7ceffa
Iterations: 16329
java.net.NoRouteToHostException: Can't assign requested address (Address not available)
at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)
at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399)
at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242)
at java.base/java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:403)
at java.base/java.net.Socket.connect(Socket.java:591)
at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:121)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:180)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:326)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:605)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:440)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:835)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
at com.demo.DemoApplication.main(DemoApplication.java:25)

您打开连接的速度比关闭连接的速度要快 - 关闭套接字在释放可用于新连接之前处于 TIME_WAIT 状态。

仅出于测试目的,您可以设置 tcp_tw_reuse允许重用 TIME_WAIT 套接字。

在我的 OSX 上,我可以更改最大段生命周期以进行测试,并且错误消失了。

sudo sysctl -w net.inet.tcp.msl=1000net.inet.tcp.msl: 15000 -> 1000

DefaultHttpClientBasicClientConnectionManager 支持,它创建和管理单个连接,并且每次只为任何路由保留一个 Activity 连接。

当连接释放回连接管理器时,它会保持 Activity 状态以供重用并标记为可重用。

If I cache the DefaultHttpClient the error does not occur.

这正是解决方案。我相信使用单个 http 客户端并允许连接管理器完成其工作的正确方法。

所有的连接管理在apache documentation 中有解释。

4.2.5 已经很老了(2013 年 4 月)。如果您开始一个新项目,那么在撰写本文时更新到最新(4.5.12)是有意义的。

引用资料:

https://cwiki.apache.org/confluence/display/HTTPCOMPONENTS/FrequentlyAskedConnectionManagementQuestions

https://raby.sh/osx-where-are-my-time_wait.html

关于java - Apache DefaultHttpClient - java.net.BindException : Address already in use: connect,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61667650/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com