9

In our application we want to achieve higher throughput so I just want to know how threading works in Spring MVC controllers.

Thanks in advance for your help.

This helped me

http://community.jaspersoft.com/wiki/how-increase-maximum-thread-count-tomcat-level

DhruvG
  • 394
  • 1
  • 2
  • 10
  • Your Java EE server (e.g. Tomcat) will handle the threading for incoming requests. Generally speaking, it's not a good idea to spawn your own threads in a Java web app. – GriffeyDog Oct 08 '15 at 20:56
  • 2
    This is really a great question, and it shows up high on google for "spring rest controller threads"; I see no reason for downvotes. Given the multithreaded nature of application servers, and of spring MVC, it is crucial to have full clarity on this subject. – P Marecki Feb 09 '16 at 13:59

3 Answers3

18

A web application is hosted in an application server (like tomcat). Usually the application server manage a thread pool and every request is handled by a thread.

The web application don't have to worry about this thread pool. The size of the thread pool is a parameter of the application server.

To achieve higher throughput you really need to identify the bottleneck.

(According my experience, the size of the thread pool of the application server is rarely the root cause of performance problem.)


Note that the "number of controller instances" is normally one. i.e. a controller is usually a singleton shared/used by all threads, and therefore a controller must be thread-safe.

ben75
  • 29,217
  • 10
  • 88
  • 134
  • I am aware of this but just wondering if I want to deploy two different applications on one server, whereas one is mission critical and other one is a rest application which isnt. How I can control number of threads for rest application. Thanks – DhruvG Oct 09 '15 at 13:12
4

Let us specify the question a little more: an application of interest, implementing a REST controller, is deployed on a typical mutlithreaded application server (running, possibly, other things as well). Q: Is there concurrence in handling of separate requests to the mapped methods of the controller?

I'm not authoritative in this subject, but it is of high importance (in particular: should single-threaded logic be applied to REST-Controller code?).

Edit: answer below is WRONG. Concurrent calls to different methods of same controller are handled concurrently, and so all shared resources they use (services, repositories etc.) must ensure thread safety. For some reason, however, calls to be handled by the same method of the controller are serialized (or: so it appears to me as of now).

The small test below shows, that even though subsequent (and rapid) calls to the mapped methods of the controller are indeed handled by different threads, single-threaded logic applies (i.e. there is no cuncurrency "out of the box").

Let us take the controller:

 AtomicInteger count = new AtomicInteger();

@RequestMapping(value = {"/xx/newproduct"})
@ResponseBody
public Answer newProduct(){
    Integer atCount = count.incrementAndGet();
    ////// Any delay/work would do here
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Answer ans = new Answer("thread:" + Thread.currentThread().getName() + " controller:" + this, atCount);
    count.decrementAndGet();
    return ans;
}

and launch 10 rapid (almost concurrent w.r.t. the 1000ms sleep time) REST requests, e.g. by the AngularJS code

$scope.newProd = function (cnt) {
    var url = $scope.M.dataSource + 'xx/newproduct';
    for(var i=0; i<cnt; ++i) {
        $http.get(url).success(function(data){
            console.log(data);
        });
    }

};

(the Answer just carries a String and an Integer; making count static would not change anything). What happens, is that all requests become pending concurrently, but responses come sequentially, exactly 1s apart, and none has atCount>1. They do come from different threads though.

More specifically the console log has: enter image description here

in other words: enter image description here

Edit: This shows, that concurrent calls to the same method/route are serialized. However, by adding a second method to the controller we easily verify, that calls to this method would be handled concurrently with the calls to the first method, and hence, multithreaded logic for handling requests is mandatory "out-of-the-box".

In order to profit from multithreading one should therefore, as it seems, employ traditional explicit methods, such as launching any non-trivial work as a Runnable on an Executor.

P Marecki
  • 1,108
  • 15
  • 19
  • Addendum: the behavior does not change even if sleep delay is reduced to 10, 1 or even 0ms. (In the last case my system handles 1000 such simple requests in 5ms; it is a separate and quite interesting isssue how does one go to, say 10k requests/second...) – P Marecki Jan 08 '16 at 17:14
  • 1
    I think that it is your client (i.e. web browser running type script) that is "serializing" requests to the same url. – ben75 Jan 17 '19 at 15:05
0

Basically this has nothing to do with Spring. Usually each request is forked into a separate thread. So the usual thing to do here is finding the bottleneck. However there is a possibility that badly written beans that share state over thread boundaries and therefore need to be synchronized might have a very bad effect.

hotzst
  • 7,238
  • 9
  • 41
  • 64
  • But I guess there should be a way to configure your application to use pre-defined number of threads (Max). – DhruvG Oct 08 '15 at 20:49
  • 1
    Where do you see a use case for delegating work to different threads? The forking of the requests happens at the level of the application server (e.g. Tomcat), so that configuration should be done there. – hotzst Oct 08 '15 at 20:55