Dan*_*lor 5 java tomcat asynchronous comet servlet-3.0
我试图使用Servlet API 3中定义的异步处理实现COMET聊天.它无法正常工作 - 聊天被阻止,所以我创建了调试servlet来仅测试异步部分.
这是我的doGet方法:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
log.debug("doGet called");
int timeout = 30 + RandomUtils.nextInt(60);
String message = RandomStringUtils.randomAlphanumeric(50 + RandomUtils.nextInt(250));
response.setHeader("Access-Control-Allow-Origin", "*");
final AsyncContext context = request.startAsync();
synchronized(items) {
items.add(new RequestItem(context, message, timeout));
}
log.debug("doGet created request and finished");
}
Run Code Online (Sandbox Code Playgroud)
我将请求项放入队列,并且有一个线程在运行,它将在指定的超时后获取项目并将响应发送到AsyncContext,打印有关它的消息.问题是,线程被阻塞,直到AsyncContext得到响应.这是在浏览器中请求4页加载后在我的日志中可见的内容:
2011-12-08 13:56:36,923 DEBUG [my.servlet.TestAsyncServlet] doGet called
2011-12-08 13:56:36,952 DEBUG [my.servlet.TestAsyncServlet] doGet created request and finished
2011-12-08 13:57:39,934 TRACE [my.servlet.TestAsyncServlet] respond on item RequestItem [context=org.apache.catalina.core.AsyncContextImpl@175870a, message=zEQpATavzwFl6qIbBKve4OzIY9UUuZBwbqN1TC5KpU3i8LM9B6ChgUqaRmcT2yF, timeout=0]
2011-12-08 13:57:39,962 DEBUG [my.servlet.TestAsyncServlet] doGet called
2011-12-08 13:57:39,962 DEBUG [my.servlet.TestAsyncServlet] doGet created request and finished
2011-12-08 13:58:53,949 TRACE [my.servlet.TestAsyncServlet] respond on item RequestItem [context=org.apache.catalina.core.AsyncContextImpl@88ee03, message=pKHKC632CPIk7hGLV0YqCbQl1qpWIoyNv5OWCp21bEqoni1gbY79HT61QEUS2eCjeTMoNEwdqKzCZNGgDngULysSzVdzFTnQQ5cQ8JvcYnp1pLVqGTueJPWnbRdUuO, timeout=0]
2011-12-08 13:58:53,960 DEBUG [my.servlet.TestAsyncServlet] doGet called
2011-12-08 13:58:53,960 DEBUG [my.servlet.TestAsyncServlet] doGet created request and finished
2011-12-08 13:59:36,954 TRACE [my.servlet.TestAsyncServlet] respond on item RequestItem [context=org.apache.catalina.core.AsyncContextImpl@197950e, message=43FPeEUZWBLqgkAqS3WOFMiHUMVvx6o4jNqWLx8kUvwxqJqpOZyGCtiIcr7yw, timeout=0]
2011-12-08 13:59:36,999 DEBUG [my.servlet.TestAsyncServlet] doGet called
2011-12-08 13:59:36,999 DEBUG [my.servlet.TestAsyncServlet] doGet created request and finished
2011-12-08 14:00:34,957 TRACE [my.servlet.TestAsyncServlet] respond on item RequestItem [context=org.apache.catalina.core.AsyncContextImpl@1cb1278, message=r69Y4NQsyR1vj0kzUlHssic2x1Yrr6T09IGKjWAH1E6Lz4VhFTy9dQHi5CPeTObyjLLBDlCLEDfiyMUnVkVIEgYG7r47Ak4w30RklhzdEi9nthqdfNkry6nyjircsFPX534NqWjI1LwsrGq5nOa3ZYtfjfPVpGlk4KDmWP11L53YntO3GmptZPKa50gcqj9i, timeout=0]
Run Code Online (Sandbox Code Playgroud)
正如它所看到的那样,只有在前一个请求(理论上是异步的)被回答之后才会调用下一个doGet方法.所以整个异步的东西根本不起作用!这是web.xml声明:
<servlet>
<servlet-name>TestAsyncServlet</servlet-name>
<servlet-class>my.servlet.TestAsyncServlet</servlet-class>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>TestAsyncServlet</servlet-name>
<url-pattern>/test-async</url-pattern>
</servlet-mapping>
Run Code Online (Sandbox Code Playgroud)
我正在做所有在互联网上找到的东西.我没有看到犯错的地方.我发现在servlet.xml中配置没什么特别之处.所以问题是,为什么它不能正常工作?
好吧,作为研究的一部分,我编写了测试程序,它打开了与tomcat的多个连接,并在异步servlet上进行了GET/POST.我已经调试并重新检查了我的server.xml配置,有限的线程池以便更好地查看测试结果等.现在我的连接器配置如下所示:
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
minProcessors="3"
maxProcessors="8"
maxThreads="20"
connectionTimeout="150000"
asyncTimeout="150000" />
Run Code Online (Sandbox Code Playgroud)
这是有效的!我已经使用NIO进行了测试,并且一次建立了1000个连接,并且所有这些连接都在一次完成.
但是,我所描述的效果仍然存在于浏览器中.当我尝试在10个选项卡上加载servlet时,首先加载,而不是第二个等等.这似乎是浏览器的行为,没有任何东西在服务器上被阻止.当我打开3个浏览器(Firefox,Chrome,Opera)时,我一次处理了3个连接.
因此,Servlet API 3.0中定义的异步处理适用于Tomcat 7,但是,它必须使用自己的程序进行测试,而不是使用浏览器中的多个选项卡...测试多个选项卡中的COMET聊天也无法按预期工作.但是,在现实生活中,一台计算机只能打开一个连接.并且,浏览器的行为不是任何服务器的错.
编辑 将Spring MVC解决方案包含到Web应用程序中后,停止了异步处理模式(忽略了web.xml中的参数).但是,可以通过添加行手动设置异步支持:
request.setAttribute("org.apache.catalina.ASYNC_SUPPORTED", true);
Run Code Online (Sandbox Code Playgroud)