【问题标题】:Intermittent "Socket closed" exception with HttpUrlConnectionHttpUrlConnection 的间歇性“套接字关闭”异常
【发布时间】:2014-06-27 07:27:38
【问题描述】:

我有一个在 jboss 7.1.1/java 1.7 下运行的 servlet 应用程序,它将 http 请求发送到另一台服务器。大部分时间一切正常,但偶尔(一天一次到几次)我们会收到“套接字关闭”异常。我一直在试图找出可能导致这种情况的原因,但到目前为止我一直没有成功。顺便说一句,当应用程序在旧版本的 Jboss/Java 下运行时,就会发生这种情况,因此版本可能不那么相关。

这是发生这种情况的方法的摘录:

。 . . . .

try

{

    HttpURLConnection conn = (HttpURLConnection) urlEndpoint.openConnection();
    conn.setRequestMethod("POST");
    conn.setDoInput(true);
    conn.setDoOutput(true);
    conn.setRequestProperty("Content-Type", "text/xml; charset=UTF-8");
    conn.setRequestProperty("charset", "UTF-8");
    DataOutputStream out = new DataOutputStream(conn.getOutputStream());
    out.write(env.getBytes("UTF-8"));
    out.flush();
    out.close();
    InputStream iss = null;
    conn.connect();
try
{
    iss = conn.getInputStream(); // this is where the exception is caught

。 . . . . .

下面是异常的样子:

。 . . . . .

java.net.SocketException: socket closed
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:150)
    at java.net.SocketInputStream.read(SocketInputStream.java:121)
    at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
    at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:633)
    at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:579)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1322)               

。 . . . . .

我看到一些帖子提到了 http 连接保持的套接字池,但我不确定这是否以及如何帮助我解决我遇到的问题。

我现在已经用尽了所有的想法,如果能提供任何帮助,我将不胜感激。

【问题讨论】:

  • 您可以尝试禁用http keepalive。 HTTP 本身有一个竞争条件,即服务器可能会在一段时间后使持久连接超时,如果您碰巧通过该现有 TCP 连接发送请求,就像该连接在服务器上超时一样,您将得到您的结果在这里。
  • 感谢您的建议 - 我一定会尝试的。但是有两个问题:1. 有没有办法检查这确实是正在发生的事情 2. 如果 keepalive 属性确实是问题的根源 - 在什么情况下不应该使用它
  • 我有一些理论,但这里有一些一般性指导。在设计一个健壮的系统时,您必须预料到 HTTP 请求会间歇性地失败。即使您的服务器有 100% 的正常运行时间,在您的客户端代码和服务器之间的网络上也可能发生无法控制的事情。因此,您应该设计您的客户端代码以预期 IOException 并执行适当的重试逻辑。
  • 我知道我上面的评论并不能真正回答您的具体和格式良好的问题。我只是想强调不要因为根本原因而被挂断,而是要为网络方面的任何事情做好准备。 EJP在下面给出的答案也很好。
  • 现在要实际提供一个答案。 EJP 所说的。此外,请求流 (out.close()) 的关闭可能会在后台发出单向套接字关闭的信号。使用 Content-Length 标头而不是关闭输入流可能会更好。这只是作为竞争条件原因的假设。

标签: java sockets httpurlconnection


【解决方案1】:

在进行任何 I/O 之前调用 conn.connect() 会更有意义。事后做这件事根本没有任何意义。您无需关闭输出流。

【讨论】:

  • EJP,您能否详细说明在这种情况下在 conn.getOutputStream() 之前调用 conn.connect() 会产生什么影响?
  • 哦,拜托。 当然很明显,除非连接对象被连接,否则写入输出流实际上不会发生?在这种情况下,它显然必须自动连接自己?在哪种情况下,在输出步骤之后调用 connect() 必须是多余的?因此毫无意义?并且毫无意义?
  • 我并不想争论——我只是想了解整个事情在引擎盖下是如何运作的,因为这对我来说并不那么明显。无论如何,我确实在发送请求之前添加了一个 conn.connect() 并运行我的测试用例,它模拟了生产中发生的情况,经过几次迭代后,它再次抛出“套接字关闭”。所以显式打开连接并没有解决主要问题。
猜你喜欢
  • 2018-05-08
  • 1970-01-01
  • 2017-07-18
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-02
  • 2019-06-29
  • 2019-12-15
相关资源
最近更新 更多