【发布时间】:2015-05-01 08:19:01
【问题描述】:
使用不同的 Java 库执行数百万个 HTTP 请求让我有线程挂起:
java.net.SocketInputStream.socketRead0()
这是native函数。
我尝试设置 Apche Http Client 和 RequestConfig 以使(我希望)一切可能的超时,但 我(可能无限)挂在 socketRead0 上。如何摆脱它们?
挂起率约为每 10000 个请求(对 10000 个不同的主机)约 1 个,并且它可能会永远持续下去(我已经确认线程挂起在 10 小时后仍然有效)。
Windows 7 上的 JDK 1.8。
我的HttpClient厂:
SocketConfig socketConfig = SocketConfig.custom()
.setSoKeepAlive(false)
.setSoLinger(1)
.setSoReuseAddress(true)
.setSoTimeout(5000)
.setTcpNoDelay(true).build();
HttpClientBuilder builder = HttpClientBuilder.create();
builder.disableAutomaticRetries();
builder.disableContentCompression();
builder.disableCookieManagement();
builder.disableRedirectHandling();
builder.setConnectionReuseStrategy(new NoConnectionReuseStrategy());
builder.setDefaultSocketConfig(socketConfig);
return HttpClientBuilder.create().build();
我的RequestConfig工厂:
HttpGet request = new HttpGet(url);
RequestConfig config = RequestConfig.custom()
.setCircularRedirectsAllowed(false)
.setConnectionRequestTimeout(8000)
.setConnectTimeout(4000)
.setMaxRedirects(1)
.setRedirectsEnabled(true)
.setSocketTimeout(5000)
.setStaleConnectionCheckEnabled(true).build();
request.setConfig(config);
return new HttpGet(url);
注意:实际上我有一些“技巧”——如果请求正确完成,我可以在其他 Thread 中安排 .getConnectionManager().shutdown() 并取消 Future,但它已被弃用,而且它会杀死整个 HttpClient,不仅那个单一的请求。
【问题讨论】:
-
好吧,他们会一直阻塞,直到数据到达或超时。你的意思是这些线程被永久阻塞而不超时?
-
是的,我的意思是它永远挂起(我检查了 6 小时场景)
-
你不认为这只是 OpenJDK 的错误吗?例如:bugs.openjdk.java.net/browse/JDK-8049846
-
截至 2017 年 2 月,仍然没有解决 Windows 挂起问题的迹象。相比之下,使用 JDK-8075484(2016 年 9 月的 JDK 9)和 JDK-8172578(2017 年 1 月的 JDK 8u152),Oracle 似乎已经修复了 linux、solaris、macosx 和 aix 中的问题。最接近的 Windows 错误似乎是 JDK-8000679。
-
Stuart Marks 决定在 2017 年 5 月关闭 JDK-8000679(此错误的 Windows 版本),遗憾地评论“这要么是 Java 网络代码中的错误,要么是 OS 网络层中的错误。关闭为不能复制。”
标签: java sockets http timeout apache-httpclient-4.x