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

前端 未结 3 575
滥情空心
滥情空心 2021-01-13 03:30

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.

<
相关标签:
3条回答
  • 2021-01-13 04:22

    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.

    0 讨论(0)
  • 2021-01-13 04:23

    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:

    in other words:

    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.

    0 讨论(0)
  • 2021-01-13 04:30

    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.

    0 讨论(0)
提交回复
热议问题