我正在尝试修复自从我们从Tomcat 6.0.26升级到7.0.52以来已经出现的Web应用程序中的错误。该应用程序基本上是从另一个网站获取内容的代理,违规代码如下:
public static synchronized void connect(String externalServiceUrl, HttpServletResponse response) throws IOException {
log.info("Connecting to " + externalServiceUrl);
URLConnection serverConnection = new URL(externalServiceUrl).openConnection();
serverConnection.setDoInput(true);
serverConnection.setDoOutput(false);
Map responseMap = serverConnection.getHeaderFields();
for (Iterator iterator = responseMap.keySet().iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
List values = (List) responseMap.get(key);
for (int i = 0; i < values.size(); i++) {
Object o = values.get(i);
response.setHeader(key, o.toString());
}
}
OutputStream toClient = response.getOutputStream();
try {
BufferedInputStream fromServer = new BufferedInputStream(serverConnection.getInputStream());
int bytie;
try {
while ((bytie = fromServer.read()) != -1) {
toClient.write(bytie); // Exception thrown from here
}
} catch (RuntimeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
fromServer.close();
} catch (IOException e) {
log.severe("Cannot connect to external service with URL " + externalServiceUrl);
e.printStackTrace();
} finally {
toClient.flush();
toClient.close();
}
}
抛出以下异常:
ClientAbortException: java.net.SocketException: Connection reset
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:413)
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:480)
at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:310)
at org.apache.catalina.connector.OutputBuffer.writeByte(OutputBuffer.java:457)
at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:77)
at org.springframework.security.web.context.SaveContextOnUpdateOrErrorResponseWrapper$SaveContextServletOutputStream.write(SaveContextOnUpdateOrErrorResponseWrapper.java:203)
at nz.cri.gns.boardaccess.proxy.ProxyHelper.connect(ProxyHelper.java:72)
...
Caused by: java.net.SocketException: Connection reset
at java.net.SocketOutputStream.socketWrite(Unknown Source)
at java.net.SocketOutputStream.write(Unknown Source)
这通常表示用户已离开页面导致浏览器关闭连接,但情况并非如此。我已经在Chrome,IE8和Firefox中测试了所有相同的结果 - 浏览器上的“网页不可用”消息以及服务器上面的堆栈跟踪。 toClient.write(bytie);
行通常执行20k +次,因此在连接关闭之前,大约有一半的文件被写入响应。这种情况发生的时间不到一秒,因此不太可能是由Tomcat的connectionTimeout设置引起的(默认设置为20000ms)。