通过 Callable 的 Spring Boot 异步控制器不起作用

问题描述 投票:0回答:1

我想创建一个与 Spring Boot 异步的端点。

我想避免使用 Future,从而避免使用 @Async,因为它强制使用 future。

我阅读并应用了本文中的代码:https://howtodoinjava.com/spring-boot/async-rest-controller-callable/

这就是我所拥有的:

用于启用异步并配置 threadPool 的配置类:

package com.howtodoinjava.springasyncexample.config;

@Configuration
@EnableAsync
public class AsyncConfig implements WebMvcConfigurer {

  @Override
  public void configureAsyncSupport(AsyncSupportConfigurer configurer) {

    configurer.setTaskExecutor(mvcTaskExecutor());
    configurer.setDefaultTimeout(30_000);
  }

  @Bean
  public ThreadPoolTaskExecutor mvcTaskExecutor() {

    ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
    threadPoolTaskExecutor.setCorePoolSize(10);
    threadPoolTaskExecutor.setThreadNamePrefix("mvc-task-");
    return threadPoolTaskExecutor;
  }
}

控制器代码:

package com.howtodoinjava.springasyncexample.web.controller;

import java.util.concurrent.Callable;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import lombok.extern.slf4j.Slf4j;

@RestController
@Slf4j
public class HelloWorldCallableController {

    @GetMapping(value = "/testCallable")
    public Callable<String> echoHelloWorld() {
        log.info("controller hit");
        return () -> {
            Thread.sleep(5000);
            log.info("finished long job");
            return "Hello World !!";
        };
    }
}

申请代码:

package com.howtodoinjava.springasyncexample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringAsyncExampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringAsyncExampleApplication.class, args);
    }
}

我打开浏览器,在两个不同的选项卡上以一秒的间隔发出两个快速请求。 我期望的是这些日志

controller hit t
controller hit t+1s
finished long job t+5s (first job finishing on work thread 1)
finished long job t+6s (second job finishing on work thread 2)

我得到的是这样的:

2024-03-26 09:50:07.356  INFO 8752 --- [nio-8080-exec-1] c.h.s.w.c.HelloWorldCallableController   : controller hit
2024-03-26 09:50:12.372  INFO 8752 --- [     mvc-task-1] c.h.s.w.c.HelloWorldCallableController   : finished long job
2024-03-26 09:50:12.398  INFO 8752 --- [nio-8080-exec-2] c.h.s.w.c.HelloWorldCallableController   : controller hit
2024-03-26 09:50:17.412  INFO 8752 --- [     mvc-task-2] c.h.s.w.c.HelloWorldCallableController   : finished long job

显然我们可以看到“控制器监听线程”在处理新请求之前等待第一个监听线程完成其工作。所以这根本不是异步行为,它只是正常的同步控制器行为。

java spring spring-boot asynchronous callable
1个回答
0
投票

万一有人像我一样在这上面浪费时间,发生这种情况的原因是我测试它的方式,我使用的是名为“Google Chrome”的浏览器。

我正在创建两个选项卡并调用相同的 URL 来在两个选项卡上进行测试(http://localhost:8080/endpoint),但 Chrome 似乎只使用 一个线程 来发出 HTTP 请求...所以它在等待在选项卡 2 上执行请求之前返回选项卡 1 上的第一个请求。

我必须使用 Postman 进行测试,创建请求的两个实例并快速连续运行它们,以有效地测试两个快速调用。原帖中的代码有效。

© www.soinside.com 2019 - 2024. All rights reserved.