Подтвердить что ты не робот

Web Reactive Programming - Каковы преимущества с точки зрения клиента HTTP?

Предположим, что эти два сценария контроллера генерируют случайные числа с задержкой:

1) Реактивная пружина 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.

Итак, кроме классных вещей (таких как хорошая семантика, композиция...), какой смысл использовать Spring Web Reactive, учитывая, что HTTP-запросы браузера не являются реактивными и эквивалентны использованию традиционного DeferredResult?

4b9b3361

Ответ 1

Есть различия, поэтому позвольте мне попытаться сломать его.

Для возвращаемого значения DeferredResult<Double[]> ясно, что массив должен быть подготовлен первым, прежде чем значение будет записано в ответ.

Spring Web Reactive записывает каждое индивидуальное значение из Flux<Double> по мере его появления. Теперь с точки зрения браузера вы можете не видеть фактической разницы, потому что он не даст вам полный массив JSON, пока он не получит полностью.

Это больше вопрос о том, как переходить в браузер? Например, если вы добавили "Accept: text/event-stream" в качестве заголовка запроса, вы можете использовать каждый двойной символ в качестве отдельного события в браузере. Таким образом, возможности сервера делать это и делать это эффективно.