消除或理解Jetty 9的“IllegalStateException:HttpChannelOverHttp关闭后数据过多”

时间:2015-04-09 00:44:05

标签: java jetty jax-ws embedded-jetty

设置

我使用jaxws-maven-plugin v2.1生成Web服务类。我还包括以下Jetty依赖项:

  • org.eclipse.jetty.jetty-server
  • org.eclipse.jetty.jetty-sevlet
  • org.eclipse.jetty.jetty-http-spi

(有问题的版本是9.2.10.v20150310,但除了知道它的Jetty 9之外,这个问题超越了Jetty的特定次要版本号。)

使用以下代码,我可以成功发布服务:

System.setProperty("com.sun.net.httpserver.HttpServerProvider",
                   "org.eclipse.jetty.http.spi.JettyHttpServerProvider");

final String url = "http://localhost/SlipperySoap";
final SlipperySoap service = new SlipperySoapImpl();
final Endpoint endpoint = Endpoint.publish(url, service);

问题

有时候,我会定期从Jetty那里收到警告:

  

badMessage:java.lang.IllegalStateException:HttpChannelOverHttp @ 38f120bc关闭后数据太多{r = 1,a = IDLE,uri = - }

这些警告通常分批进行,如以下时间戳显示:

08:33:43.510 [pool-1-thread-4641] WARN : HttpParser: badMessage: ...
08:33:47.778 [pool-1-thread-4556] WARN : HttpParser: badMessage: ...
08:33:48.340 [pool-1-thread-4612] WARN : HttpParser: badMessage: ...
08:33:49.037 [pool-1-thread-4567] WARN : HttpParser: badMessage: ...
08:33:49.112 [pool-1-thread-4721] WARN : HttpParser: badMessage: ...
08:33:49.242 [pool-1-thread-4579] WARN : HttpParser: badMessage: ...
08:33:49.344 [pool-1-thread-4698] WARN : HttpParser: badMessage: ...
08:33:49.470 [pool-1-thread-4504] WARN : HttpParser: badMessage: ...
08:33:50.260 [pool-1-thread-4553] WARN : HttpParser: badMessage: ...
08:33:54.834 [pool-1-thread-4721] WARN : HttpParser: badMessage: ...
08:34:01.194 [pool-1-thread-4763] WARN : HttpParser: badMessage: ...
08:34:01.675 [pool-1-thread-4715] WARN : HttpParser: badMessage: ...
08:34:02.262 [pool-1-thread-4504] WARN : HttpParser: badMessage: ...
08:34:02.880 [pool-1-thread-4699] WARN : HttpParser: badMessage: ...
08:34:05.530 [pool-1-thread-4570] WARN : HttpParser: badMessage: ...
08:34:09.634 [pool-1-thread-4570] WARN : HttpParser: badMessage: ...
08:34:10.081 [pool-1-thread-4504] WARN : HttpParser: badMessage: ...
08:34:10.298 [pool-1-thread-4738] WARN : HttpParser: badMessage: ...
08:34:13.508 [pool-1-thread-4688] WARN : HttpParser: badMessage: ...
08:34:23.360 [pool-1-thread-4755] WARN : HttpParser: badMessage: ...
08:34:23.557 [pool-1-thread-4717] WARN : HttpParser: badMessage: ...

我试图了解这是否是导致我错过处理这些请求的合法问题,或者这是否是可以被抑制和忽略的良性警告。

如果这是一个合法的问题,我是否可以在服务器端采取任何措施来消除它(或者这是一个行为错误的客户端的问题?)。

注意我无法控制连接到此Web服务的客户端。因此,任何解决方案都必须在服务器端实现。

已经探索过的途径

堆栈溢出

有一个Stack Overflow帖子"Jetty too much data after closed for HttpChannelOverHttp",但答案都是低质量的,并不寻求理解核心问题。我尝试更改Jetty默认缓冲区大小,但这没有解决问题(这并不让我感到惊讶)。

Google网上论坛

Google Groups discussion建议:

  

这只是一个警告,应该没问题。 IIRC会在强行关闭连接时发生这种情况。

这并没有提供足够的细节让我感到满意,这是一个良性的信息 - 缓冲区中的数据被丢弃而不是处理,所以我需要了解导致这种情况的原因。 为什么另一端发送请求然后在读取响应之前关闭连接?这条消息还有其他解释吗?

Jetty来源

Jetty source code说:

/**
 * Parse until next Event.
 * @return True if an {@link RequestHandler} method was called and it returned true;
 */
public boolean parseNext(ByteBuffer buffer)
{
   ...

   // handle end states
   if (_state==State.END)
   {
     // eat white space
     while (buffer.remaining()>0 && buffer.get(buffer.position())<=HttpTokens.SPACE)
       buffer.get();
   }
   else if (_state==State.CLOSED)
   {
     if (BufferUtil.hasContent(buffer))
     {
       // Just ignore data when closed
       _headerBytes+=buffer.remaining();
       BufferUtil.clear(buffer);
       if (_maxHeaderBytes>0 && _headerBytes>_maxHeaderBytes)
       {
         // Don't want to waste time reading data of a closed request
         throw new IllegalStateException("too much data after closed");
       }
     }
   }
   ...

这又引出了一个问题,为什么在状态进展到关闭后还有待处理的数据。这是否是在关闭TCP连接之前没有等待读取响应的行为不当的客户端的签名?

1 个答案:

答案 0 :(得分:6)

这是发出请求的客户端的结果,http行为意味着交换(请求和/或响应)应该关闭连接(请求标头已启动或服务器标头已启动),但客户端仍在发送请求后的内容(标题和正文内容)。

最常见的情况:编写错误的客户端希望连接是持久的,但不遵循http规范并查看指示连接状态的标头,然后继续发出另一个请求。

另一种常见情况:写得不好的客户端发送请求头和(可选)请求体,但也会在请求体之后发送一些额外的字节。这将被解释为另一个需要处理的请求,但是初始交换已经关闭连接,使得解析这些额外的字节会发出“关闭后数据过多”的警告