Web 响应式编程 - 从 HTTP 客户端的角度来看有哪些优势?

Web Reactive Programming - What are the advantages from the HTTP client point of view?

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

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 让我们认为它在生成结果时将结果发回,但实际上它不会那样发生,客户端将无法处理结果,直到生成所有数字。

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

因此,除了很酷的东西(例如漂亮的语义、组合......),考虑到浏览器 HTTP 请求不是,使用 Spring Web Reactive 有什么意义reactive 并且等同于使用传统的 DeferredResult?

有差异所以让我试着分解一下。

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

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

这更多是关于如何流式传输到浏览器的问题?例如,如果您将 "Accept: text/event-stream" 添加为请求 header,您就可以在浏览器中将每个 double 作为单独的事件使用。所以服务器有能力做到这一点并且高效地做到这一点。