15

让我们假设控制器的这两种情况会延迟生成一些随机数:

1) 反应式 Spring 5 反应式应用程序:

@GetMapping("/randomNumbers")
public Flux<Double> getReactiveRandomNumbers() {
    return generateRandomNumbers(10, 500);
}

/**
 * Non-blocking randon number generator
 * @param amount - # of numbers to generate
 * @param delay - delay between each number generation in milliseconds
 * @return
 */
public Flux<Double> generateRandomNumbers(int amount, int delay){
    return Flux.range(1, amount)
               .delayMillis(delay)
               .map(i -> Math.random());
}

2)传统的Spring MVC DeferredResult

@GetMapping("/randomNumbers")
public DeferredResult<Double[]> getReactiveRandomNumbers() {
    DeferredResult<Double[]> dr = new DeferredResult<Double[]>();

    CompletableFuture.supplyAsync(() -> {
        return generateRandomNumbers(10, 500);
    }).whenCompleteAsync((p1, p2) -> {
        dr.setResult(p1);
    });

    return dr;
}

/**
 * Blocking randon number generator
 * @param amount - # of numbers to generate
 * @param delay - delay between each number generation in milliseconds
 * @return
 */
public Double[] generateRandomNumbers(int amount, int delay){
    int generated = 0;
    Double [] d = new Double[amount];
    while(generated < amount){
        try {
            Thread.sleep(delay);
        } catch (InterruptedException e) {}
        d[generated] = Math.random();
        generated++;
    }
    return d;
}

从 HTTP 客户端(浏览器、AJAX 请求)的角度来看,两种方案之间没有任何区别。我的意思是客户端将等到所有结果都发送完毕,并且在提交整个响应之前不会处理它们。

也就是说,尽管 spring web reactive 让我们认为它正在将结果发送回来,因为它们正在生成,但实际上它不会发生这种情况,并且客户端将无法处理结果,直到所有数字都有已生成。

使客户端完全响应的直接方法是使用 WebSockets。

那么,除了很酷的东西(比如漂亮的语义、组合......),考虑到浏览器 HTTP 请求不是响应式的并且等效于使用传统的 DeferredResult,使用 Spring Web Reactive 的意义何在?

4

1 回答 1

15

存在差异,所以让我尝试将其分解。

对于DeferredResult<Double[]>返回值,显然必须先准备好数组,然后才能将值写入响应。

Spring Web Reactive 确实从 a 中写入每个单独的值,Flux<Double>因为它变得可用。现在从浏览器的角度来看,您可能看不到实际的差异,因为在完整接收到 JSON 数组之前,它不会为您提供完整的 JSON 数组。

这更多的是如何流式传输到浏览器的问题?例如,如果您添加"Accept: text/event-stream"为请求标头,则可以在浏览器中将每个双精度作为单独的事件使用。因此,服务器有能力做到这一点并有效地做到这一点。

于 2016-08-04T14:52:27.230 回答