Moni
Moni

Reputation: 949

Why is Spring DeferredResult executed serially in my app?

I am trying to build a REST web server where GET requests are non-blocking, even if it needs to make a slightly time consuming call.

@RestController
public class Endpoint {
    static int callCount = 0;

    @RequestMapping (value = "/endpoints", method = RequestMethod.GET)
    public DeferredResult<Integer> someGetMethod() {
        System.out.println("Mita: GET Called. Count#: " + callCount++);
        DeferredResult<Integer> deferredResult = new DeferredResult<>();
        new Thread( () -> {
            deferredResult.setResult(getSomething());
        }).start();
        System.out.println("Mita: Thread started");
        return deferredResult;
    }

    private int getSomething() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 100;
    }
}

To test, I sent two GET requests from Restlet, to the same endpoint, in intervals of around 2 seconds. Yet, I see the following in DEBUG level logs of my spring application.

2017-08-26 01:16:38.231 DEBUG 1252 --- [nio-8080-exec-1] o.a.coyote.http11.Http11InputBuffer      : Received [GET /endpoints/ HTTP/1.1
Host: localhost:8080
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
Accept: */*
DNT: 1
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8,es;q=0.6,zh-CN;q=0.4,zh;q=0.2
 ]
...
...
2017-08-26 01:16:43.399 DEBUG 1252 --- [nio-8080-exec-2] o.a.coyote.http11.Http11InputBuffer      : Received [GET /endpoints/ HTTP/1.1
Host: localhost:8080
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
Accept: */*
DNT: 1
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8,es;q=0.6,zh-CN;q=0.4,zh;q=0.2

]

Notice, how the two requests came right after 5 seconds, the exact interval I have called sleep for (even though I had sent the request ~2 seconds after the first one). So, it seems like tomcat is sequentializing the incoming requests. How can I make tomcat not to sequentialize the requests? Or is it that I am missing something very obvious.

Upvotes: 2

Views: 365

Answers (1)

tsolakp
tsolakp

Reputation: 5948

Using DeferredResult (or Servlet asynch mode that it uses) wont prevent the client (in this case Restlet) not to wait 5 seconds before it gets response from the first request.

To the client calling your Spring endpoint will look just as if the Spring endpoint was not using asynch mode at all. This means that Restlet or Tomcat can potentially wait till first request is finished before serving second request to your endpoint.

Upvotes: 1

Related Questions