Jetty、Spring 和 SPDY 的 Web 服务器日志中的异常
Posted
技术标签:
【中文标题】Jetty、Spring 和 SPDY 的 Web 服务器日志中的异常【英文标题】:Exception in web server logs with Jetty, Spring, and SPDY 【发布时间】:2014-08-24 01:06:13 【问题描述】:在对 Spring MVC Web 应用程序进行休息调用时,我收到以下错误消息。浏览器收到正确的响应,但我希望异常消失。任何帮助都会很棒。
我正在使用 Jetty 9.2.0.v20140526、Spring 框架 4.0.5.RELEASE 和 NPN 1.1.6.v20130911 (SPDY) 运行 Web 服务器
错误信息
[STDERR] java.lang.IllegalStateException: not lastContent, no content and no responseInfo!
[STDERR] at org.eclipse.jetty.spdy.server.http.HttpTransportOverSPDY.send(HttpTransportOverSPDY.java:164)
[STDERR] at org.eclipse.jetty.spdy.server.http.HttpTransportOverSPDY.send(HttpTransportOverSPDY.java:97)
[STDERR] at org.eclipse.jetty.server.HttpChannel.sendResponse(HttpChannel.java:733)
[STDERR] at org.eclipse.jetty.server.HttpChannel.write(HttpChannel.java:766)
[STDERR] at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:134)
[STDERR] at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:127)
[STDERR] at org.eclipse.jetty.server.HttpOutput.flush(HttpOutput.java:229)
[STDERR] at java.io.FilterOutputStream.flush(FilterOutputStream.java:140)
[STDERR] at org.eclipse.jetty.servlets.gzip.AbstractCompressedStream.flush(AbstractCompressedStream.java:125)
[STDERR] at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:209)
[STDERR] at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:143)
[STDERR] at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:89)
[STDERR] at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:193)
[STDERR] at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71)
[STDERR] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122)
[STDERR] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
[STDERR] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
[STDERR] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
[STDERR] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
[STDERR] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
[STDERR] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
[STDERR] at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
[STDERR] at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
[STDERR] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
[STDERR] at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
[STDERR] at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:751)
[STDERR] at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1666)
[STDERR] at org.eclipse.jetty.servlets.UserAgentFilter.doFilter(UserAgentFilter.java:83)
[STDERR] at org.eclipse.jetty.servlets.GzipFilter.doFilter(GzipFilter.java:351)
[STDERR] at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1645)
[STDERR] at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:564)
[STDERR] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
[STDERR] at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:578)
[STDERR] at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221)
[STDERR] at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1111)
[STDERR] at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:498)
[STDERR] at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:183)
[STDERR] at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1045)
[STDERR] at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
[STDERR] at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:199)
[STDERR] at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109)
[STDERR] at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:98)
[STDERR] at org.eclipse.jetty.server.Server.handle(Server.java:461)
[STDERR] at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:284)
[STDERR] at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:241)
[STDERR] at org.eclipse.jetty.spdy.server.http.HttpChannelOverSPDY.run(HttpChannelOverSPDY.java:87)
[STDERR] at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:607)
[STDERR] at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:536)
[STDERR] at java.lang.Thread.run(Thread.java:744)
Spring 代码来自我的控制器
@Controller
public class TestController
@RequestMapping(value="/run/test", method=RequestMethod.GET, produces="text/plain")
@ResponseBody
protected String runTest() throws IOException
return "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012";
如果我使返回值的大小更小,它最终将毫无例外地工作。不知道为什么大尺寸是个问题...
Maven Plugin Config 从 pom.xml 启动 Jetty
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.0.v20140526</version>
<configuration>
<scanIntervalSeconds>5</scanIntervalSeconds>
<stopKey>STOP</stopKey>
<stopPort>9999</stopPort>
<jettyXml>src/main/etc/jetty.xml, src/main/etc/jetty-spdy.xml</jettyXml>
<contextXml>src/main/etc/context.xml</contextXml>
<waitForChild>true</waitForChild>
<jvmArgs>-Xbootclasspath/p:$settings.localRepository/org/mortbay/jetty/npn/npn-boot/1.1.6.v20130911/npn-boot-1.1.6.v20130911.jar -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -Dspring.profiles.active=dev</jvmArgs>
</configuration>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-http-server</artifactId>
<version>9.2.0.v20140526</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<version>9.2.0.v20140526</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-rewrite</artifactId>
<version>9.2.0.v20140526</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp</artifactId>
<version>9.2.0.v20140526</version>
</dependency>
</dependencies>
</plugin>
更新:如果我删除 gzip 的 servlet 过滤器,它就可以工作。
来自 web.xml
<filter>
<filter-name>GzipFilter</filter-name>
<filter-class>org.eclipse.jetty.servlets.GzipFilter</filter-class>
<init-param>
<param-name>mimeTypes</param-name>
<param-value>text/html,text/plain,text/xml,application/xhtml+xml,text/css,application/javascript,image/svg+xml,application/json</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>GzipFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
【问题讨论】:
我试过你的休息端点把它丢给我,在tomcat上运行。无异常返回字符串,等待其他响应。 如果我关闭 NPN (SPDY) 支持,那么一切正常。出于性能原因,我希望启用 NPN。 【参考方案1】:当我尝试在空流上flush()
时,我遇到了类似的异常。它只发生在 SPDY 上,所以对于这个协议,我有 flush()
的特殊版本,它检查是否可以刷新流。
在我的输出流中flush()
看起来像:
synchronized public void flush()
throws IOException
// out.flush() do not work on an empty SPDY output stream!!!
// it ends with:
// java.lang.IllegalStateException: not lastContent, no content and no responseInfo!
// at org.eclipse.jetty.spdy.server.http.HttpTransportOverSPDY.send(HttpTransportOverSPDY.java:164)
// this is a reason for "flushed" variable
if (flushed)
return;
out.flush();
flushed = true;
// flush
在write()
方法中,如果我将一些字节写入输出流,我会设置flushed = false
。
我的班级使用out = response.getOutputStream()
,它可以是 SPDY 输出流(会引发异常),也可以是 HTTP/HTTPS 输出流,它可以是 flush()
空流而不会出现错误。
【讨论】:
如您所见,我使用自己的输出。我不知道如何使用我在您的问题中看到的 XML 配置来做到这一点。【参考方案2】:您运行的是什么版本的 Java?尝试改变它并比较结果。另外,尝试使用过滤器的bufferSize
和minGzipSize
初始化参数。请参阅文档here
【讨论】:
我正在使用java-7以上是关于Jetty、Spring 和 SPDY 的 Web 服务器日志中的异常的主要内容,如果未能解决你的问题,请参考以下文章