Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Lets suppose these two scenarios of a controller that generates some random numbers with a delay:

1) Reactive Spring 5 reactive application:

@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) Traditional Spring MVC with 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;
}

From the perspective of a HTTP client (browser, AJAX request) there isn't any difference between both scenarios. I mean the client will wait until all the results are sent, and won't process them until the whole response is committed.

That is to say, although spring web reactive makes us think that it's sending the results back as they are being produced, in reality it doesn't happen that way and the client won't be able to process the results until all the numbers have been generated.

The straightforward way to make the client fully reactive would be to use WebSockets.

So, apart from the cool stuff (such as nice semantics, composition...), what is the point of using Spring Web Reactive considering that browser HTTP requests aren't reactive and are equivalent to using the traditional DeferredResult?

like image 238
codependent Avatar asked Aug 04 '16 07:08

codependent


People also ask

What are the advantages of reactive programming?

Simple to handle – a significant advantage of reactive programming is that it is simple to manage as a developer. Individual data streams can have code blocks added or removed, enabling you to make any necessary changes via the stream in question.

What is reactive web client?

WebClient is a non-blocking, reactive client for performing HTTP requests with Reactive Streams back pressure. WebClient provides a functional API that takes advantage of Java 8 Lambdas. By default, WebClient uses Reactor Netty as the HTTP client library. But others can be plugged in through a custom.

What is the use of reactive programming?

Reactive programming describes a design paradigm that relies on asynchronous programming logic to handle real-time updates to otherwise static content. It provides an efficient means -- the use of automated data streams -- to handle data updates to content whenever a user makes an inquiry.

What is WebFlux used for?

Spring WebFlux makes it possible to build reactive applications on the HTTP layer. It is a reactive fully non-blocking, annotation-based web framework built on Project Reactor that supports reactive streams back pressure and runs on non-blocking servers such as Netty, Undertow and Servlet 3.1+ containers.


1 Answers

There are differences so let me try to break it down.

For the DeferredResult<Double[]> return value clearly the array has to be prepared first before the value can be written to the response.

Spring Web Reactive does write each individual value from a Flux<Double> as it becomes available. Now from a browser perspective you may not see an actual difference because it won't give you the full JSON array until it's received in its entirety.

This is more a question of how to stream into a browser? For example if you add "Accept: text/event-stream" as a request header you can then consume each double as an individual event in the browser. So the capability of the server to do it and do it efficiently is there.

like image 167
Rossen Stoyanchev Avatar answered Sep 30 '22 18:09

Rossen Stoyanchev