Async Spring Контроллеры против обычных контроллеров

Я хотел проанализировать улучшение, которое я вижу, включив Async-контроллеры в Spring Загрузка через обычный контроллер

Итак, вот мой тестовый код. Один API возвращает Callable, а другой - обычный API-интерфейс контроллера. Оба блока API блокируют 10 сек., имитируя задачу с длительным сроком выполнения

@RequestMapping(value="/api/1",method=RequestMethod.GET)
    public List<String> questions() throws InterruptedException{
        Thread.sleep(10000);
        return Arrays.asList("Question1","Question2");
    }

    @RequestMapping(value="/api/2",method=RequestMethod.GET)
    public Callable<List<String>> questionsAsync(){
        return () -> {
            Thread.sleep(10000);
            return Arrays.asList("Question2","Question2");
        };
    }

Я установил встроенный tomcat с этой конфигурацией i.e только один поток обработки tomcat:

server.tomcat.max-threads=1
logging.level.org.springframework=debug

Ожидания для /api/ 1 Поскольку существует только один поток tomcat, другой запрос не будет рассмотрен до тех пор, пока он не будет обработан после 10 секунд

Результаты: Познакомьтесь с ожиданиями


Ожидания для /api/ 2 Поскольку мы возвращаем вызываемый немедленно, единственный поток tomcat должен освобождать обработку другого запроса. Callable будет внутренне запускать новый поток. Поэтому, если вы нажмете один и тот же api, он также будет принят.

Результаты: Этого не происходит, и до тех пор, пока вызываемый не выполнится полностью, дальнейший запрос не будет рассмотрен.

Вопрос Почему /api/ 2 не работает должным образом?

Ответ 1

@DaveSyer прав, /api/ 2 действительно ведет себя так, как ожидалось.

Я предполагаю, что вы тестируете поведение с помощью веб-браузера. По крайней мере, Firefox и Chrome предотвращают одновременное одновременное обращение к одному и тому же URL. Если вы открываете 2 вкладки с помощью api/2, второй отправляет запрос в приложение только после первого ответа.

Попробуйте протестировать его с помощью простого bash script, например:

curl localhost/api/2 &
curl localhost/api/2 &
curl localhost/api/2 &

Он будет печатать 3 ответа примерно в одно и то же время.