Контроллер 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).

Это не тот случай, когда контроллер заблокирует все последующие вызовы, пока занят. Это многопоточный.

Другие вопросы по тегам