如何与SpringBoot的@RestController并行处理多个请求?

时间:2017-02-11 13:36:04

标签: java spring-boot parallel-processing

我对Spring Boot比较陌生,从他们getting started site的一个非常简单的例子开始,这是(在控制器端):

@RestController
public class HelloController {

    @RequestMapping("/")
    public String index() {
        return "Greetings from Spring Boot!";
    }

}

我现在想要的是,可以在并行中提供同一控制器的多个(可能长时间运行)请求

由于我已经知道@RestController将被实例化为单例,我很清楚,多个请求(由同一方法处理)将被顺序处理 更新:我的不好:我认为这与控制器是单身人士的事实有关。但事实是:为什么它不能并行运行呢?

所以我按照以下方式更改了上面的示例,以便在每个请求上创建一个新的控制器实例,并使用一些方法检查实际发生的情况:

@RestController
@Scope(value = "request")
public class HelloController {

    private static AtomicInteger count = new AtomicInteger(0);

    public HelloController() {
        count.incrementAndGet();
    }

    @PostConstruct
    public void init() {
        System.out.println("start request " + count);
    }

    @PreDestroy
    public void onDestroy() {
        System.out.println("end request " + count);
    }

    @RequestMapping("/")
    public String index() throws InterruptedException {
        LocalDateTime now = LocalDateTime.now();
        TimeUnit.SECONDS.sleep(15);
        System.out.println(now);
        return "Greetings from Spring Boot! " + now + "  " + count.get();
    }

}

现在我希望看到请求在大约15秒内并行处理,但实际上我只能看到它显然是顺序处理的,需要30秒(在stdout上):

start request 1
2017-02-11T14:19:47.429
end request 1
start request 2
2017-02-11T14:20:02.467
end request 2

所以我的问题是:如何实现这些请求是并行处理的,因为为每个请求创建一个实例显然是不够的?

小言语:我已经尝试将@Asnync注释与@EnableAsync结合使用,但是这似乎是“火上浇油”,这样我就无法得到回应在客户端。

stackoverflow上的几个条目(例如thisthis)很有意思,但也没有回答我的问题,本教程也没有回答asynchronous methods

更新:由于有几个人指出问题可能与我测试的方式有关,因此我尝试使用其他浏览器运行它。有趣的是,我在Chrome和Firefox上遇到了同样的问题。但是当从每个请求做一个请求时,它显示了预期的行为(并行地提供请求) - 所以我被浏览者愚弄了......

3 个答案:

答案 0 :(得分:2)

您写道:

  

因为我已经知道@RestController将被实例化为   单身,对我来说很明显,多个请求(这是   由相同方法处理)将按顺序处理。

" ...将按顺序处理 " - 这是虚假陈述。我甚至不知道它的基础是什么。在使方法同步(或将使用其他锁技术)之前,可以通过多个线程同时访问它。

在第二种情况下,您只是将其配置为为每个请求创建新实例。我只有一个想法,解释为什么在调试器中收到顺序结果:你也顺序执行浏览器中的这些请求。

如果您想测试即使是第一种情况如何完美处理乘法请求,只需在浏览器中打开单独的选项卡并几乎同时启动请求。

答案 1 :(得分:1)

作为单例的控制器与是否可以同时访问无关。

除非你有一些不能跨线程共享的可变字段,否则你真的不需要使用基于请求的作用域,但实现类似的东西可能只是糟糕的设计。

我想你看到这两个请求需要30秒的原因是因为你实际上并没有发出并发请求,而是等待第一个请求在开始第二个请求之前完成。

答案 2 :(得分:0)

我从2009年开始使用Spring,我知道他们的Controller是Singleton。 但这并不意味着他们按顺序处理您的请求(等待一个完成,然后执行下一个请求。)

Spring Boot网站的示例代码能够处理并行请求。它将创建next()的单例实例,但Spring可以同时多次调用HelloController(并行)。

index()