Shc*_*ein 9 java tcp http httpurlconnection
首先,一些背景.有一个工作人员扩展/解决了一堆短URL:
http://t.co/example -> http://example.com
Run Code Online (Sandbox Code Playgroud)
所以,我们只是按照重定向.而已.我们不会从连接中读取任何数据.在我们得到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 ...
Run Code Online (Sandbox Code Playgroud)
经过简单的研究,我明白skip()在将数据流发送回连接池之前会调用它来清理流(如果设置了keep-alive?).我仍然不明白如何避免这种情况.此外,我怀疑代码中是否存在一些不良设计或JDK中存在问题.
所以,问题是:
close()?例如,保证一些合理的超时.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);} ...
Run Code Online (Sandbox Code Playgroud)
在我看来,JDK本身存在一个错误.不幸的是,重现这个很难......
KeepAliveStream您已链接的实施违反了合同,available()并且skip()保证是非阻塞的,因此可能确实会阻止.
available()的契约保证了一个非阻塞skip():
返回可以从此输入流中读取(或跳过)的字节数的估计值,而不会被此输入流的方法的下一个调用者阻塞.下一个调用者可能是同一个线程或另一个线程.单个读取或跳过这么多字节不会阻塞,但可以读取或跳过更少的字节.
每次调用skip()多次执行调用available():
if (nskip <= available()) {
long n = 0;
// The loop below can iterate several times,
// only the first call is guaranteed to be non-blocking.
while (n < nskip) {
nskip = nskip - n;
n = skip(nskip);
}
Run Code Online (Sandbox Code Playgroud)
这并不能证明您的应用程序因KeepAliveStream错误使用而阻止InputStream.一些实现InputStream可能提供更强的非阻塞保证,但我认为这是一个非常可能的怀疑.
编辑:经过一番研究,这是JDK最近修复的一个错误:https: //bugs.openjdk.java.net/browse/JDK-8004863 ? page = com.atlassian.jira.plugin.system.issuetabpanels:全tabpanel.错误报告说有关无限循环,但阻塞skip()也可能是结果.修复似乎解决了这两个问题(skip()每个只有一个available())
| 归档时间: |
|
| 查看次数: |
2954 次 |
| 最近记录: |