Контроллер REST многопоточный?
Я делал этот урок о том, как вернуть асинхронный вызываемый объект. Работает как задумано. Но в то время как первый запрос спит в течение 5 секунд, я получаю второй запрос, контроллер ожидает завершения предыдущего запроса, прежде чем обработать второй.
Как заставить контроллер обрабатывать сразу каждый запрос и делать сон в фоновом режиме?
@Редактировать
Пример: представьте себе ситуацию, когда моему контроллеру необходимо сделать запрос к внешнему API и на основании его ответа он должен отправить свой собственный ответ. Внешний вызов API занимает, скажем, 2 секунды. Я хочу, чтобы пользователи моего приложения ждали только 2,5 секунды и не помещались в очередь, потому что контроллер может обрабатывать только один запрос за раз.
2 ответа
Контроллер REST многопоточный?
Контроллер REST является многопоточным, так как DisptcherServlet
обрабатывает несколько запросов от клиентов одновременно и обслуживает их с помощью соответствующих методов контроллера. Вы можете сослаться на поток обработки запросов здесь
Как заставить контроллер обрабатывать сразу каждый запрос и делать сон в фоновом режиме?
Вы можете сделать это, вернувшись Callable<String>
в методе контроллера Spring, как показано ниже:
@Controller
public class MyController {
@RequestMapping(value="/sleep")
public Callable<String> myControllerMethod() {
Callable<String> asyncTask = () -> { try {
System.out.println(" WAITING STARTED:"+new Date());
Thread.sleep(5000);
System.out.println(" WAITING COMPLETED:"+new Date());
return "Return";//Send the result back to View Return.jsp
} catch(InterruptedException iexe) {
//log exception
return "ReturnFail";
}};
return asyncTask;
}
Выход:
Ожидание началось: четверг, 24 ноября 21:03:12 GMT 2016
Ожидание завершено: четверг, 24 ноября 21:03:17 GMT 2016
После этого в представлении будет возвращена страница "Return.jsp".
Здесь метод контроллера будет запущен в отдельном потоке (освобождая реальный поток сервлета), и как только задача будет выполнена, Результат будет снова отправлен клиенту (Просмотр и т. Д.).
PS: нужно добавить @EnableAsync
как часть конфигурации вашего приложения, вы можете посмотреть здесь.
То, что вы хотите сделать, это то, что должно быть сделано в первом примере учебника, который вы связали:
@RequestMapping(value = "/block", method = RequestMethod.GET, produces = "text/html")
public String executeSlowTask() {
logger.info("Request received");
Thread.sleep(5000);
logger.info("Servlet thread released");
return result;
}
Это блокирует вызывающий поток и ждет, пока это не будет сделано. Если вы звоните из другого HTTP-сеанса, это будет другой поток, так что это будет новое 5-секундное ожидание (не затронутое первым).
Потоки связаны с HTTP-вызовами, если в пуле есть доступные потоки (конфигурация сервера tomcat).
Это не тот случай, когда контроллер заблокирует все последующие вызовы, пока занят. Это многопоточный.