【发布时间】: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