Java.io.IOException: Разбитая труба

В настоящее время мы переносим устаревшее приложение на Jetty. И у меня есть какое-то исключение в отношении сломанной трубы.

  • Java 6
  • Jetty 8.1.8
  • Spring 3.2.0

Я пытаюсь перенести веб-приложение Glassfish на 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

Когда я проверяю stacktrace, я видел, что это исключение вызвано всегда запросом 404.

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

  • Почему у меня такое исключение?
  • Как я могу воспроизвести это исключение на своей машине локально?

Ответ 1

Самая распространенная причина, по которой я столкнулся с "сломанным трубой", состоит в том, что одна машина (пары, подключаемой через сокет) закрыла свой конец сокета до того, как связь была завершена. Около половины из них были связаны с тем, что программа, сообщающая об этом сокете, прекратилась.

Если программа, отправляющая байты, отправляет их и немедленно выключает сокет или завершает себя, возможно, что сокет перестает функционировать до того, как байты будут переданы и прочитаны.

Попробуйте помещать паузы в любом месте, где вы закрываете сокет, и перед тем, как разрешить программе завершить работу, чтобы узнать, помогает ли это.

FYI: "pipe" и "socket" - это термины, которые иногда используются как взаимозаменяемые.

Ответ 2

Я согласен с @arcy, проблема на стороне клиента, в моем случае это было из-за nginx, позвольте мне уточнить Я использую nginx в качестве интерфейса (чтобы я мог распространять нагрузку, ssl и т.д.) И используя proxy_pass http://127.0.0.1:8080 для перенаправления соответствующих запросов на tomcat.

Существует значение по умолчанию для переменной nginx proxy_read_timeout of 60s, которая должна быть достаточной, но в некоторые моменты пика моя установка будет ошибочной с помощью java.io.IOException: неработающая труба, изменяющая значение, поможет до тех пор, пока не возникнет первопричина (Должно быть достаточно 60 секунд).

ПРИМЕЧАНИЕ. Я сделал новый ответ, поэтому я мог немного расширить свое дело (это было единственное упоминание, которое я нашел об этой ошибке в Интернете после довольно многого).

Ответ 3

По сути, происходит то, что ваш пользователь либо закрывает вкладку браузера, либо переходит на другую страницу, прежде чем связь будет завершена. Ваш веб-сервер (Jetty) генерирует это исключение, потому что он не может отправить оставшиеся байты.

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. Игнорируйте это конкретное исключение, чтобы не регистрировать его.
  2. Сделайте ваш код более эффективным/упакованным, чтобы он передавал меньше данных. (Не всегда вариант!)

Ответ 4

увеличить response.getBufferSize() получить размер буфера и сравнить с байтами, которые вы хотите перенести!