Spring MVC и Ajax-запросы в одном контроллере - PullRequest
3 голосов
/ 05 августа 2011

У меня есть следующая настройка контроллера в Spring 3.0.5. Tomcat Webserver 7.0.14 с хостом Windows 7.

    @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.
   }


  }

Я выполняю запрос ajax из Firefox или IE следующим образом. Результат тот же

   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);
    }

});

Ответчик Ajax работает правильно, за исключением случаев, когда он вызывается во время метода POST "create". Поэтому я запускаю ajax-запрос в цикле, в то время как метод create (который обрабатывает POST) не выполняется, он возвращает нормально. Однако во время выполнения create Ajax-ответы являются прерывистыми, и Ajax-запросы часто не отвечают. Сервер не блокируется и не останавливается, а просто перестает отвечать на метод состояния, в то время как метод create что-то делает.

Я попытался заменить большую часть создания циклами, которые заполняют массивы. Я получил больше ответов ajax, но не один рядом с одним, в лучшем случае получил 20-30 ответов из 100. Я также протестировал изменение значений для объекта состояния, чтобы убедиться, что значения вернут действительный JSON. Они все работали. Выполняя тест, в котором я только что заполнил древовидные карты и массивы, я также наблюдал за Jconsole и менеджером задач на наличие признаков ограничения ресурсов. HTe JVM никогда не использовала более 50% доступной памяти, а более эффективные операции ввода-вывода, ОЗУ или ЦП были где-то близко к загрузке.

Очевидно, что-то здесь не так. Я попытался присоединить аннотацию @Async к контроллеру Ajax и к обработчику POST, но, похоже, это не внесло никаких изменений. Я также пытался выставить тайм-ауты и автоматически прерывать запрос.

Из 100 запросов Ajax я получаю один ответ ... остальные, кажется, заблокированы. Либо до вызова блока создания, либо после, ответы будут мгновенными. Я не должен перегружать браузер. Рассматриваемый запрос ajax срабатывает один раз в четверть секунды (средство обновления индикатора выполнения). Даже если я уменьшу количество запросов Ajax до 1 в секунду (или даже 1 в 2 с), результат будет тем же. Вызовы ajax выполняются вовремя, поэтому сторона JS работает как положено.

Я использовал wireshark, чтобы я мог видеть входящий запрос ajax. Я могу учесть большинство запросов ajax в том, что я вижу, как они достигают сервера. Я вижу, как они попадают в обработчик, но сообщения об устранении неполадок (System.out.println) появляются только тогда, когда метод create не занят. Понятно, что «занято» означает обработку результатов запросов, которые он делает, а «не занято» означает ожидание ответа. Никакие защелки или семафоры не используются. Добавление аннотации Spring @Async не имело никакого значения.

Кто-нибудь знает, что здесь происходит? Кажется, что-то блокируется и мешает ответу? Контроллер заблокирован для одного потока?

1 Ответ

1 голос
/ 13 августа 2011

Помните, что браузер имеет только 2-4 потока на домен (в зависимости от браузера), поэтому он не будет делать более 2-4 запросов одновременно, поэтому ваш веб-сервер должен отправлять эти ответы вовремя, чтобы они нетайм-аут.Одновременная отправка 100 запросов, вероятно, будет просто отброшена, если вы не вернете их в течение ~ 10 мс.

Когда вы отправляете запрос 100, вы видите все эти 100 запросов в методе создания?Регистрируете ли вы некоторые данные, когда они начинаются и когда заканчиваются, чтобы вы могли сопоставить их все?Я бы удостоверился, что вы получаете все 100 запросов из браузера на сервере и генерируете ответ на каждые 100 запросов.Используйте log4j, чтобы вы могли видеть имя потока, обслуживающего каждый запрос.Эти имена потоков помогут вам идентифицировать каждый отдельный запрос, чтобы вы могли сопоставлять сообщения, зарегистрированные в начале и в конце.System.out, вы не получите это из коробки.

Для дополнительного тестирования попробуйте это.Что произойдет, если вы отправите только 10 запросов на браузер?Вы получаете все это?Если это так, то умножьте на 2 и посмотрите, получите ли вы все эти и т. Д., Пока не начнете видеть, что они выпадают.

Я надеюсь, что вы просто тестируете производительность, пытаясь отправить 100 запросов за сеанс браузера, в противном случае выуничтожит ваш сервер, когда вы начнете работать, и 30 000 браузеров х 100 = 3 миллиона запросов попадут на эту страницу.Если вы не просто тестируете материал, я бы серьезно подумал о том, чтобы изменить то, что вы делаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...