异步 Spring 控制器与普通控制器

Async Spring Controllers vs normal Controllers

我想分析通过在 Spring 中启用异步控制器在普通控制器上启动

我可能看到的改进

这是我的测试代码。一个 API returns 一个 Callable,另一个是普通控制器 API。两个 APIs 阻塞 10secs 模拟一个长的 运行 task

@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,即只有一个 tomcat 处理线程:

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

期望 /api/1 由于只有一个 tomcat 线程,在 10 秒

后处理之前不会受理另一个请求

结果: 达到预期


期望 /api/2 由于我们立即返回一个可调用对象,因此单个 tomcat 线程应该可以自由处理另一个请求。 Callable 将在内部启动一个新线程。所以如果你点击相同的 api 它也应该被接受。

结果: 这不会发生,直到可调用函数完全执行,才会接受进一步的请求。

问题 为什么 /api/2 没有按预期运行?

@DaveSyer 是对的,/api/2 实际上表现符合预期。

我假设您正在使用网络浏览器测试行为。至少 Firefox 和 Chrome 正在阻止对同一个 URL 的多个同时请求。如果您使用 api/2 打开 2 个选项卡,第二个选项卡只会在第一个得到响应后才向应用程序发送请求。

尝试使用简单的 bash 脚本对其进行测试,例如:

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

它将大约同时打印 3 个响应。

只想提一下 server.tomcat.max-threads 自 Spring 引导 2.3 以来已弃用。现在在 Spring application.properties 中使用 server.tomcat.threads.max。默认值为 200。