Java 我该如何预防;“断管”;从我的tomcat网站上撤下来?
我有一个Tomcat 8 web应用程序,它使用2MB png图像作为“启动/登录页”背景。图像在外部样式表中被引用 如果我清除浏览器缓存,直接请求图像的URL,但在图像加载之前离开图像,它将完全杀死我的web应用程序。它无法为任何请求提供更多响应 我得到这个错误:Java 我该如何预防;“断管”;从我的tomcat网站上撤下来?,java,tomcat8,Java,Tomcat8,我有一个Tomcat 8 web应用程序,它使用2MB png图像作为“启动/登录页”背景。图像在外部样式表中被引用 如果我清除浏览器缓存,直接请求图像的URL,但在图像加载之前离开图像,它将完全杀死我的web应用程序。它无法为任何请求提供更多响应 我得到这个错误: org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe at org.apache.catalina.
org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:396)
at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:344)
at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:421)
at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:409)
at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:97)
at org.apache.catalina.servlets.DefaultServlet.copy(DefaultServlet.java:1795)
at org.apache.catalina.servlets.DefaultServlet.serveResource(DefaultServlet.java:919)
at org.apache.catalina.servlets.DefaultServlet.doGet(DefaultServlet.java:400)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at other.JsCssImgResponseHeaderFilter.doFilter(JsCssImgResponseHeaderFilter.java:36)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at other.CatchAnyExceptionFilter.doFilter(CatchAnyExceptionFilter.java:39)
我试图捕获该异常(或任何与此相关的异常)并显示一个友好的ErrorPage.jsp,但我无法重定向到ErrorPage,因为响应已经提交
我无法在测试环境中复制它,但我可以在生产中随意使其中断
有人知道我解决这类问题的选择吗?提前谢谢
顺便说一句,下面是我的Filter类的doFilter方法的外观:
public void doFilter(ServletRequest req,
ServletResponse res,
FilterChain fc) throws IOException, ServletException
{
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession();
try
{
fc.doFilter(req, res);
// Have learned that response headers should not be set until we have determined there won't be an exception.
// Can't easily redirect or forward (to an error page, for example) if headers have already been committed.
if (SessionHelper.hasNeedsJsCssImgResponseHeaderFlag(request))
{
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, JsCssImgResponseHeaderFilter.SECONDS_TO_CACHE);
response.setHeader("Cache-Control", "PUBLIC, max-age=" + JsCssImgResponseHeaderFilter.SECONDS_TO_CACHE + ", must-revalidate");
response.setHeader("Expires", DateUtils.getDateInExpiresHeaderFormat(cal.getTime()));
}
else if (SessionHelper.hasNeedsDynamicPageResponseHeaderFlag(request))
{
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Expires", "Mon, 25 Nov 2013 00:00:01 GMT"); // in the past
}
else if (SessionHelper.hasNeedsRestServicesResponseHeaderFlag(request))
{
// CORS - Cross Origin Resource Sharing: allow service requests from other domains --
// such as local development domains hosting AngularJS projects.
response.setHeader("Access-Control-Allow-Origin", "http://localhost.domain.com:8080");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, DELETE");
// response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, X-Requested-With");
}
}
catch (Exception e)
{
SessionHelper.setErrorPageException(req, session, e);
final String uri = request.getRequestURI();
final String playerName = SessionHelper.getLoggedInPlayerName(session);
String outerLogEntryText = "Player = " + playerName + " - IP = " + request.getRemoteAddr() +
" - Mobile = " + SessionHelper.isMobileBrowser(request) +
" - URI = " + uri + " - Exception MSG = " + e.getMessage();
LogUtils.writeLogEntry(outerLogEntryText, true, e);
SessionHelper.setRedirectPage(session, SessionHelper.ERROR_PAGE_PATH);
}
finally
{
String redirectPage = SessionHelper.getRedirectPage(session);
SessionHelper.clearRedirectPage(session);
if (redirectPage != null)
{
if (response.isCommitted())
{
// Article: http://stackoverflow.com/questions/11305563/cause-of-servlets-response-already-committed
System.out.println("Response has been committed. Cannot redirect to: " + redirectPage);
}
else
{
response.sendRedirect(redirectPage);
}
}
}
}
当问题发生时,我的“Response has committed…”输出语句确实被写入,因此它不会重定向到我的错误页面。这就是我面临的挑战:当这种情况发生时,如何重定向到某个地方——或者采取一些更好/无害的措施。在做了一些更改之后,这个问题在生产中没有出现。最有影响的改变是减小了背景/飞溅图像的大小。另一个变化是,我将Tomcat连接器connectionTimeout属性设置增加了6倍。使用什么浏览器重要吗?铬v。火狐v。工业工程v。狩猎?你说的“离开”到底是什么意思?关闭页面?切换选项卡?是否转到同一站点上的其他页面?断开的管道表示服务器和客户端之间的连接在页面加载完成之前已断开。顺便说一句,一个站点上的2mb图像太小了,即使它是唯一的东西。这个异常已经被捕获。这意味着它甚至没有杀死抛出的线程,更不用说整个Tomcat了。我认为问题出在其他地方。Khuderm,我所说的“导航离开”是指单击其他地方的链接——比如浏览器书签栏上指向其他站点的链接。从最初的帖子开始,我就把我的背景图片大小减少到539kb.EJP,是的,异常被捕获了。从技术上讲,它可能没有杀死Tomcat,但我的web应用程序停止响应请求,Tomcat Manager web应用程序不再工作。我必须重新启动Tomcat服务才能恢复。