hellojava
hellojava

Reputation: 5064

Async Spring Controllers vs normal Controllers

I wanted to analyze the improvement I may see by enabling Async Controllers in Spring Boot over normal controller

So here is my test code. One API returns a Callable and another is normal controller API. Both APIs block for 10secs simulating a long running task

@RequestMapping(value="/api/1",method=RequestMethod.GET)
    public List<String> questions() throws InterruptedException{
        Thread.sleep(10000);
        return Arrays.asList("Question1","Question2");
    }

    @RequestMapping(value="/api/2",method=RequestMethod.GET)
    public Callable<List<String>> questionsAsync(){
        return () -> {
            Thread.sleep(10000);
            return Arrays.asList("Question2","Question2");
        };
    }

I set up embedded tomcat with this configuration i.e only one tomcat processing thread:

server.tomcat.max-threads=1
logging.level.org.springframework=debug

Expectations for /api/1 Since there is only one tomcat thread, another request will not be entertained untill this is processed after 10secs

Results: Meet expectations


Expectations for /api/2 Since we are returning a callable immediately, the single tomcat thread should get free to process another request. Callable would internally start a new thread. So if you hit the same api it should also gets accepted.

Results: This is not happening and untill the callable executes completely, no further request is entertained.

Question Why is /api/2 not behaving as expected?

Upvotes: 11

Views: 2753

Answers (2)

ARK
ARK

Reputation: 1

Just want to mention that server.tomcat.max-threads is deprecated since Spring boot 2.3. Now use server.tomcat.threads.max in your Spring application.properties. The default is 200.

Upvotes: 0

Jakub Wach
Jakub Wach

Reputation: 199

@DaveSyer is right, /api/2 is actually behaving as expected.

I assume you are testing the behavior with a web browser. At least Firefox and Chrome are preventing multiple simultaneous requests to the same URL. If you open 2 tabs with api/2, the second one will only send a request to the application after the first got the response.

Try testing it with a simple bash script, like:

curl localhost/api/2 &
curl localhost/api/2 &
curl localhost/api/2 &

It will print 3 responses around the same time.

Upvotes: 14

Related Questions