【发布时间】:2013-01-17 12:16:14
【问题描述】:
首先,一些背景知识。有一个工人扩展/解析一堆短网址:
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() 来清理流(如果设置了keep-alive?)。我仍然不明白如何避免这种情况。此外,我怀疑我们的代码中是否存在一些糟糕的设计,或者 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 本身存在一个错误。不幸的是,这很难重现......
【问题讨论】:
标签: java http tcp httpurlconnection