java - Tomcat 7 异步处理失败 - 只有一个请求同时处理

标签 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");
}

我将请求项目放入队列,并且有一个线程正在运行,它将在指定的超时后获取项目并将响应发送到 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]

正如所见,下一个 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>

我所做的一切都是为了在 Internet 上找到。我看不出错误的地方。我发现在 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" />

这是有效的!我用 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);

关于java - Tomcat 7 异步处理失败 - 只有一个请求同时处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8431547/

相关文章:

c# - 如何使用 svcutil 生成异步方法?

java - 后续测试方法中的驱动程序对象没有被执行

java - 测试 StarTeam 操作

java - tomcat7 servlet中的内存泄漏

java - 如何使用java web applet访问系统文件?

mysql - tomcat 应用程序中的 Wait_timeout

java - Android 当前时间毫秒

java - iText 5.4.2 是开源的吗?

javascript - Node js如何每2秒运行一次axios.get?

javascript - 使用回调函数更新 JSON 对象