简体   繁体   中英

Spring MVC and Ajax requests in the same controller

I have the following controller setup in Spring 3.0.5. Tomcat Webserver 7.0.14 with Windows 7 host.

    @Controller
    @RequestMapping (value="myForm")
    public class SubmitClassController {


    //Status object with getters and setters
    Status myStatus= newStatus();

   @RequestMapping (method=RequestMethod.GET)
    public String getMyForm (Model getModel){
    //setup form
   //very simple adds one attribute to the model and returns view
    }

    @RequestMapping (value="/myFormStatus",method=RequestMethod.POST)
    public @ResponseBody Status getStatus(){
    //Ajax responder handles a null (empty) request and responds with results of status obj
    //Has System.out.println prior to return that shows variables when processed correctly
    System.out.printlin ("vars are: "+myStatus.getStatus()+" "+myStatus.getCurStep()+" "+myStatus.getTotSteps());
     return myStatus;
     }

    @RequestMapping (method=RequestMethod.POST)
    public String create (@Valid MyFormText submitText ...){
   // processes the form submitted and sets status object variables while doing so .
   //many steps each one is bascily query a remote DB wait for response, add response to the set  repeat. After each query myStatus has its status,curStap and totstep set.
   }


  }

I perform the ajax request as follows from firefox or IE the result is the same

   Ext.Ajax.request({
    url: './myForm/myFormStatus',
    method: 'POST',
    success: function(result, request) {
        var json = Ext.decode(result.responseText);
        pbar.updateProgress(json.step / json.steps, 'Working on ' + json.status + ' Step ' + json.step + ' of ' + json.steps + '...');

    },
    failure: function(result, request) {
        Ext.MessageBox.alert('Failed runner', result.responseText);
    }

});

The Ajax responder works correctly except when called during the "create" POST method. So I run the ajax query in a loop while the create method ( which handles the POST) is not running it returns fine . However while the create is running Ajax responses are intermittent and Ajax requests are often not responded to. The server does not lock up and freeze rather it just stop responding to the status method while the create method is actually doing something.

I tried replacing the bulk of the create with loops that fill arrays . I got more ajax responses but no where near one for one , at best a got 20-30 responses out of 100. I also tested changing the values for the status object to confirm that the values would return valid JSON. They all worked. While running the test where I just filled treemaps and arrays I also watched Jconsole and the task manager for signs of a resource constraint. HTe JVM never used more then 50% of its available memory and the niether I/O,RAM or CPU were anywhere close to loaded.

Clearly something is wrong here . I tried attaching the @Async annotation to both the Ajax controller and to the POST handler but this did not seem to make any changes. I also tried putting timeouts and auto aborts on the request.

Out of 100 Ajax requests I get one response...the rest appear to be blocked. Either before the create block is called or after, responses are instant. I should not be overloading the browser. The ajax request in question is set to fire once every quarter second ( progress bar updater ). Even if I throttle the ajax request back to 1 per second (or even 1 per 2 secs) the result is the same. The ajax calls are made on time so JS side is working as expected.

I used wireshark so i can see the ajax request coming in. I can account the the majority of the ajax requests in that i can see them reaching the server. I can see them hit the handler but troubleshooting (System.out.println) messages only appear when the "create" method is not "busy". To be clear "busy" means processing the results of the queries it makes, "not busy" seems to be mean waiting for a response.No latches or semaphores are being used. Adding the Spring @Async annotation did not make any difference.

Anyone know whats going on here ? Its seems something is getting locked and preventing a response? Is a controller locked to a single thread ?

Remember browser only has 2-4 threads per domain (depending on browser) so it won't make more than 2-4 requests at a time, so your web server has to send those responses back in time for them to not timeout. Sending 100 requests all at once would probably just get dropped if you didn't get those back in ~10ms.

When you send out 100 request do you see all of those 100 request in the create method? Are you logging some data when it starts and when it finishes so you can correlate they all got there? I'd make sure your getting all 100 requests from the browser in the server and generated a response for each 100 requests. Use log4j so you can see the thread name servicing each request. Those thread names will help you identify each individual request so you can match up messages logged at the start and end. System.out you don't get that out of the box.

For more testing try this. What happens if you only send 10 requests per browser? Do you get all of those? If so then multiply by 2 and see if you get all of those, etc until you start to see them drop off.

I hope you're just testing performance by trying to send 100 requests per browser session otherwise you'll destroy your server when you goto production and 30,000 browsers x 100 = 3 Million requests hit that page. If you are not just testing stuff I'd seriously consider redesigning what you're doing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM