首先,一些背景。有一个工人可以扩展/解决一堆短网址:
http://t.co/example -> http://example.com
所以,我们只遵循重定向。就是这样。我们不会从连接中读取任何数据。在我们得到 200 之后,我们立即返回最终 URL 并关闭 InputStream。
现在,问题本身。在生产服务器上,其中一个解析器线程挂在InputStream.close()
调用中:
"ProcessShortUrlTask" prio=10 tid=0x00007f8810119000 nid=0x402b runnable [0x00007f882b044000]
java.lang.Thread.State: RUNNABLE
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.skip(BufferedInputStream.java:352)
- locked <0x0000000561293aa0> (a java.io.BufferedInputStream)
at sun.net.www.MeteredStream.skip(MeteredStream.java:134)
- locked <0x0000000561293a70> (a sun.net.www.http.KeepAliveStream)
at sun.net.www.http.KeepAliveStream.close(KeepAliveStream.java:76)
at java.io.FilterInputStream.close(FilterInputStream.java:155)
at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.close(HttpURLConnection.java:2735)
at ru.twitter.times.http.URLProcessor.resolve(URLProcessor.java:131)
at ru.twitter.times.http.URLProcessor.resolve(URLProcessor.java:55)
at ...
经过简短的研究,我了解到skip()
在将流发送回连接池之前调用它来清理流(如果设置了保持活动状态?)。我仍然不明白如何避免这种情况。此外,我怀疑我们的代码中是否存在一些糟糕的设计,或者 JDK 中是否存在问题。
所以,问题是:
- 有没有可能避免挂在上面
close()
?例如,保证一些合理的超时。 - 是否可以完全避免从连接中读取数据?请记住,我只想要最终 URL。其实,我想,我根本不想
skip()
被叫……
更新:
KeepAliveStream,第 79 行,close()
方法:
// Skip past the data that's left in the Inputstream because
// some sort of error may have occurred.
// Do this ONLY if the skip won't block. The stream may have
// been closed at the beginning of a big file and we don't want
// to hang around for nothing. So if we can't skip without blocking
// we just close the socket and, therefore, terminate the keepAlive
// NOTE: Don't close super class
try {
if (expected > count) {
long nskip = (long) (expected - count);
if (nskip <= available()) {
long n = 0;
while (n < nskip) {
nskip = nskip - n;
n = skip(nskip);} ...
在我看来,JDK 本身存在越来越多的错误。不幸的是,很难重现这个......