java.io.IOException:管道损坏

我们目前正在将遗留应用程序迁移到Jetty。 我有一个关于管道破裂的例外情况。

  • Java 6
  • docker8.1.8
  • 春季3.2.0

我正在尝试将Glassfish Web应用程序迁移到Jetty。 在我们的测试环境中,我们使用负载均衡器,一切正常。 我们的客户没有任何问题。

WARN [2013-04-03 13:34:28,963] com.myapp.bbb.config.MvcDefaultConfig$1: Handler execution resulted in exception ! org.eclipse.jetty.io.EofException: null ! at org.eclipse.jetty.http.HttpGenerator.flushBuffer(HttpGenerator.java:914) ! at org.eclipse.jetty.http.HttpGenerator.complete(HttpGenerator.java:798) ! at org.eclipse.jetty.server.AbstractHttpConnection.completeResponse(AbstractHttpConnection.java:642) ! at org.eclipse.jetty.server.Response.complete(Response.java:1234) ! at org.eclipse.jetty.server.Response.sendError(Response.java:404) ! at org.eclipse.jetty.server.Response.sendError(Response.java:416) ! at org.springframework.web.servlet.DispatcherServlet.noHandlerFound(DispatcherServlet.java:1111) ! at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:898) ! at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) ! at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915) ! at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:811) ! at javax.servlet.http.HttpServlet.service(HttpServlet.java:735) ! at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796) ! at javax.servlet.http.HttpServlet.service(HttpServlet.java:848) ! at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:669) ! at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1336) ! at com.magnetdigital.maggy.dropwizard.head2get.Head2GetFilter.doFilter(Head2GetFilter.java:22) ! at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1307) ! at com.yammer.dropwizard.servlets.ThreadNameFilter.doFilter(ThreadNameFilter.java:29) ! at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1307) ! at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:453) ! at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:229) ! at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1072) ! at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:382) ! at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193) ! at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1006) ! at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135) ! at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116) ! at com.yammer.metrics.jetty.InstrumentedHandler.handle(InstrumentedHandler.java:200) ! at org.eclipse.jetty.server.handler.GzipHandler.handle(GzipHandler.java:275) ! at com.yammer.dropwizard.jetty.BiDiGzipHandler.handle(BiDiGzipHandler.java:123) ! at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:154) ! at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116) ! at org.eclipse.jetty.server.Server.handle(Server.java:365) ! at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:485) ! at org.eclipse.jetty.server.BlockingHttpConnection.handleRequest(BlockingHttpConnection.java:53) ! at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:926) ! at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:988) ! at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:635) ! at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235) ! at org.eclipse.jetty.server.BlockingHttpConnection.handle(BlockingHttpConnection.java:72) ! at org.eclipse.jetty.server.nio.BlockingChannelConnector$BlockingChannelEndPoint.run(BlockingChannelConnector.java:298) ! at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608) ! at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543) ! at java.lang.Thread.run(Thread.java:662) Caused by: ! java.io.IOException: Broken pipe ! at sun.nio.ch.FileDispatcher.write0(Native Method) ! at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:29) ! at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:69) ! at sun.nio.ch.IOUtil.write(IOUtil.java:26) ! at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:334) ! at org.eclipse.jetty.io.nio.ChannelEndPoint.flush(ChannelEndPoint.java:293) ! at org.eclipse.jetty.server.nio.BlockingChannelConnector$BlockingChannelEndPoint.flush(BlockingChannelConnector.java:253) ! at org.eclipse.jetty.http.HttpGenerator.flushBuffer(HttpGenerator.java:850) !... 44 common frames omitted 

当我检查堆栈跟踪时,我看到这个exception是由404请求引发的。

org.springframework.web.servlet.DispatcherServlet.noHandlerFound(DispatcherServlet.java:1111)

  • 为什么我有这个例外?
  • 如何在本地机器上重现此exception?

我用过“破管”的最常见原因是一台机器(通过sockets进行通信的一对机器)在通信完成之前关闭了它的sockets端。 其中大约一半是因为在该套接字上进行通信的程序已经终止。

如果发送字节的程序将它们发送出去并立即关闭套接字或终止自身,则套接字可能在发送和读取字节之前停止运行。

尝试在暂停套接字的任何地方暂停,然后再允许程序终止以查看是否有帮助。

仅供参考:“管道”和“套管”是有时可互换使用的术语。

我同意@arcy,问题是在客户端,在我的情况下是因为nginx,让我详细说明我使用nginx作为前端(所以我可以分发load,ssl等…)并使用proxy_pass http://127.0.0.1:8080将适当的请求转发给tomcat。

nginx变量proxy_read_timeout的默认值为60s应该足够了,但是在某些高峰时刻我的设置会因java.io.IOException而出错更改值的proxy_read_timeout 管道将有助于直到根本原因(60s应该足够了) )可以修复。

注意:我做了一个新的答案,所以我可以用我的案例进一步扩展(这是我在互联网上看到很多后发现这个错误的唯一提示)

基本上,正在发生的事情是您的用户要么在通信完成之前关闭浏览器选项卡,要么导航到另一个页面。 您的Web服务器(Jetty)生成此exception,因为它无法发送剩余的字节。

 org.eclipse.jetty.io.EofException: null ! at org.eclipse.jetty.http.HttpGenerator.flushBuffer(HttpGenerator.java:914) ! at org.eclipse.jetty.http.HttpGenerator.complete(HttpGenerator.java:798) ! at org.eclipse.jetty.server.AbstractHttpConnection.completeResponse(AbstractHttpConnection.java:642) ! 

这不是应用程序逻辑方面的错误。 这仅仅是由于用户行为。 您的代码本身没有任何问题。

您可以做两件事:

  1. 忽略此特定exception,以便您不记录它。
  2. 使您的代码更高效/打包,以便传输更少的数据。 (并不总是一种选择!)

增加response.getBufferSize()获取缓冲区大小并与要传输的字节进行比较!