Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC Rest Services - Number of Threads (Controller Instances)

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

like image 411
DhruvG Avatar asked Oct 08 '15 20:10

DhruvG


2 Answers

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.

like image 58
ben75 Avatar answered Sep 29 '22 21:09

ben75


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.

like image 21
P Marecki Avatar answered Sep 29 '22 20:09

P Marecki