Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tomcat 7.0.32 +Spring MVC Servlet 3 Async is not working

I wrote very simple controller which test Servlet 3 features:

@Autowired
    ThreadPoolTaskExecutor taskExecutor;

    @RequestMapping(value="{name}", method = RequestMethod.GET)
    public @ResponseBody DeferredResult<MyResponse> getShopInJSON(@PathVariable String name) {

        DeferredResult<MyResponse> df = new DeferredResult<MyResponse>();
        taskExecutor.submit(new MyRunnable(df));    

        return df; 
    }

In separate Thread I'm doing nothing but 5 second sleep command and after it I return MyResult POJO to DeferredResult.

My web.xml file is according to Servlet 3 specifications:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                             http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0"
         metadata-complete="true">
  <display-name>Archetype Created Web Application</display-name>
    <servlet>
    <async-supported>true</async-supported>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

My Connector tomcat is the following:

 <Connector port="8080" protocol="HTTP/1.1"
                maxThreads="5"
                acceptCount="5"
                connectionTimeout="20000"
                redirectPort="8443" />

Now this is the interesting part. When running simple program which opens 10 concurrent connection I see that only 5 connections are served first and second 5 connections are served after first set is released (You can see it from time stemps). This is not how Servlet 3.0 should behave

Fri May 31 01:17:57 IDT 2013: Preparing 10 concurrent connections
Fri May 31 01:18:02 IDT 2013: Output from Server int thread 9 :{"props1":"param1","props2":"param1"}
Fri May 31 01:18:02 IDT 2013: Output from Server int thread 8 :{"props1":"param1","props2":"param1"}
Fri May 31 01:18:02 IDT 2013: Output from Server int thread 4 :{"props1":"param1","props2":"param1"}
Fri May 31 01:18:02 IDT 2013: Output from Server int thread 7 :{"props1":"param1","props2":"param1"}
Fri May 31 01:18:02 IDT 2013: Output from Server int thread 2 :{"props1":"param1","props2":"param1"}
Fri May 31 01:18:07 IDT 2013: Output from Server int thread 1 :{"props1":"param1","props2":"param1"}
Fri May 31 01:18:07 IDT 2013: Output from Server int thread 0 :{"props1":"param1","props2":"param1"}
Fri May 31 01:18:07 IDT 2013: Output from Server int thread 5 :{"props1":"param1","props2":"param1"}
Fri May 31 01:18:07 IDT 2013: Output from Server int thread 6 :{"props1":"param1","props2":"param1"}
Fri May 31 01:18:07 IDT 2013: Output from Server int thread 3 :{"props1":"param1","props2":"param1"}

If change Tomcat Connector to

   <Connector connectionTimeout="200000" maxThreads="5" port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="8443"/>

it works like charm. I don't want to do it. According to Tomcat docs I should receive Servlet 3.0 functionality without Http11NioProtocol connector.

What is wrong?

like image 995
danny.lesnik Avatar asked May 30 '13 22:05

danny.lesnik


People also ask

Does servlet 3 support async requests?

Introduction In this quick tutorial, we're going to focus on the Servlet 3 support for async requests, and how Spring MVC and Spring Security handle these. The most basic motivation for asynchronicity in web applications is to handle long running requests.

How to integrate spring security with servlet webasyncmanager?

According to the official docs, Spring Security integrates with WebAsyncManager. The first step is to ensure our springSecurityFilterChain is set up for processing asynchronous requests. We can do it either in Java config, by adding following line to our Servlet config class:

How does asynccontext trigger Tomcat to return a response?

... After the HTTP servlet gets the AsyncContext object, any thread that executes acontext.complete () triggers Tomcat to return the response to the client. Surprisingly, I got this behavior by just returning Callable:

What is async @async in Spring MVC?

3. Spring MVC Async Spring 3.0 introduced the @Async annotation. @Async ‘s goal is to allow the application to run heavy-load jobs on a separate thread. Also, the caller can wait for the result if interested. Hence the return type must not be void, and it be can be any of Future, CompletableFuture, or ListenableFuture.


1 Answers

The problem is due to the maxThreads=5 setting in your Tomcat config.

For the non-NIO case, this setting does not only restrict the maximum number of request processing threads but also restricts the maximum number of connections !

Since you have not specified maxConnections, it is choosing a default value for maxConnections. Here is the excerpt from Tomcat doc on how it chooses the default value for maxConnections:

maxConnections : The maximum number of connections that the server will accept and process at any given time. When this number has been reached, the server will not accept any more connections until the number of connections falls below this value. The operating system may still accept connections based on the acceptCount setting. Default value varies by connector type. For BIO the default is the value of maxThreads unless an Executor is used in which case the default will be the value of maxThreads from the executor. For NIO the default is 10000. For APR/native, the default is 8192.

You can explicitly specify a maxConnections="10" (for example) setting to override this default behavior. You should then see that you can get 10 parallel requests getting processed regardless of the Connector used. I tried this and it works.

like image 180
2020 Avatar answered Nov 08 '22 17:11

2020