dropwizard org.eclipse.jetty.io.EofException:早期 EOF 异常

Posted

技术标签:

【中文标题】dropwizard org.eclipse.jetty.io.EofException:早期 EOF 异常【英文标题】:dropwizard org.eclipse.jetty.io.EofException: Early EOF exception 【发布时间】:2018-07-27 17:39:42 【问题描述】:

我在某些请求中遇到以下异常。它很少发生,比如一周一两次。任何想法可能导致此问题或有关我应该在哪里进行调试的任何建议。

Dropwizard 版本:1.1.4 码头服务器版本:2.25.1

错误发生在以下代码行:request.bufferEntity()

private String getBody(ContainerRequestContext requestContext) 
        if (requestContext instanceof ContainerRequest) 
            ContainerRequest request = (ContainerRequest) requestContext;
            // calling bufferEntity(), without this the entity is marked as closed and causes IllegalStateExceptions
            // on any subsequent read attempt
            request.bufferEntity();
            return request.readEntity(String.class);
         else 
            // this should never happen as we are using jersey as the jax-rs implementation engine
            throw new RuntimeException("ContainerRequestContext is not an instance of jersey ContainerRequest");
        
    

未能缓冲消息内容输入流。在 org.glassfish.jersey.message.internal.InboundMessageContext.bufferEntity(InboundMessageContext.java:931) 在 org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:132) 在 org.glassfish.jersey.server.ContainerFilteringStage.apply(ContainerFilteringStage.java:68) 在 org.glassfish.jersey.process.internal.Stages.process(Stages.java:197) 在 org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:318) 在 org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) 在 org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) 在 org.glassfish.jersey.internal.Errors.process(Errors.java:315) 在 org.glassfish.jersey.internal.Errors.process(Errors.java:297) 在 org.glassfish.jersey.internal.Errors.process(Errors.java:267) 在 org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) 在 org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) 在 org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) 在 org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) 在 org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) 在 org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) 在 org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) 在 org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473) 在 org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166) 在 org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155) 在 org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) 在 org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) 在 com.codahale.metrics.jetty9.InstrumentedHandler.handle(InstrumentedHandler.java:241) 在 io.dropwizard.jetty.RoutingHandler.handle(RoutingHandler.java:52) 在 org.eclipse.jetty.server.handler.gzip.GzipHandler.handle(GzipHandler.java:454) 在 io.dropwizard.jetty.BiDiGzipHandler.handle(BiDiGzipHandler.java:68) 在 org.eclipse.jetty.server.handler.StatisticsHandler.handle(StatisticsHandler.java:169) 在 org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) 在 org.eclipse.jetty.server.Server.handle(Server.java:564) 在 org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:317) 在 org.eclipse.jetty.server.HttpChannelOverHttp.earlyEOF(HttpChannelOverHttp.java:239) 在 org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1444) 在 org.eclipse.jetty.server.HttpConnection.parseRequestBuffer(HttpConnection.java:351) 在 org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:234) 在 org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279) 在 org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:110) 在 org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:289) 在 org.eclipse.jetty.io.ssl.SslConnection$3.succeeded(SslConnection.java:149) 在 org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:110) 在 org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124) 在 org.eclipse.jetty.util.thread.Invocable.invokePreferred(Invocable.java:128) 在 org.eclipse.jetty.util.thread.Invocable$InvocableExecutor.invoke(Invocable.java:222) 在 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:294) 在 org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:199) 在 org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:673) 在 org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:591) 在 java.lang.Thread.run(Thread.java:748) 引起:org.eclipse.jetty.io.EofException:早期 EOF 在 org.eclipse.jetty.server.HttpInput$3.getError(HttpInput.java:1104) 在 org.eclipse.jetty.server.HttpInput$3.noContent(HttpInput.java:1093) 在 org.eclipse.jetty.server.HttpInput.read(HttpInput.java:307) 在 java.io.InputStream.read(InputStream.java:101) 在 org.glassfish.jersey.message.internal.ReaderWriter.writeTo(ReaderWriter.java:115) 在 org.glassfish.jersey.message.internal.InboundMessageContext.bufferEntity(InboundMessageContext.java:918) ...省略了68个常用框架

【问题讨论】:

你运行的是什么版本的码头?这里没有足够的信息,但我的猜测是客户端过早地关闭了您的过滤器无法正常处理的连接。 【参考方案1】:

这个问题在1.3.8中依然存在,是open issue。

嗯。似乎有一种解决方法。您可以创建一个过滤器类来过滤异常并检查 Early Eof。这是一个非常适合我的案例的黑客。但是,你明白了。我已经对此进行了测试,并且可以正常工作。这是过滤器 sn-p。


  @Override
  public void doFilter(
      final ServletRequest request,
      final ServletResponse response,
      final FilterChain chain)
      throws IOException, ServletException 
    try 
      chain.doFilter(request, response);
     catch (ServletException e) 
      if (isEarlyEofException(e)) 
        log.debug("EOF Exception encountered - client disconnected during stream processing.", e);

        if (response instanceof HttpServletResponse) 
          ((HttpServletResponse) response).setStatus(HttpServletResponse.SC_BAD_REQUEST);
        
       else 
        throw e;
      
    
  

  private boolean isEarlyEofException(final ServletException e) 
    return e.getCause() instanceof ProcessingException
        && e.getCause().getCause() instanceof EofException
        && e.getCause().getCause().getMessage().equals(EARLY_EOF_MSG);
  

然后你应用过滤器。

  private void addEarlyEofExceptionFilter(final Environment environment) 
    final FilterRegistration.Dynamic filter =
        environment.servlets().addFilter("EarlyEofExceptionFilter", EarlyEofExceptionFilter.class);

    filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
  

【讨论】:

以上是关于dropwizard org.eclipse.jetty.io.EofException:早期 EOF 异常的主要内容,如果未能解决你的问题,请参考以下文章

DropWizard/Jersey API 客户端

使用 Dropwizard 客户端支持 SPDY

使用dropwizard--加入swagger

更改 Dropwizard 默认端口

如何从单元测试运行 dropwizard 服务器

使用Dropwizard-配置分类ConfiguredBundle