2016-08-04 30 views
13

Läßt diese beiden Szenarien einer Steuerung annehmen, dass eine Menge von Zufallszahlen mit einer Verzögerung erzeugt:Spring 5 Web Reactive Programming - Was sind die Vorteile aus Sicht des HTTP-Clients?

1) Reactive Feder 5 reaktive Anwendung:

@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) Tradicional Spring MVC mit 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; 
} 

aus der Sicht eines HTTP-Client (Browser, AJAX-Request) ist es nicht irgendein Unterschied zwischen beiden Szenarien. Ich meine, der Client wird warten, bis alle Ergebnisse gesendet sind, und wird sie nicht verarbeiten, bis die gesamte Antwort festgeschrieben ist.

Das heißt, obwohl spring web reactive macht uns denken, dass es sendet die Ergebnisse zurück, wie sie produziert werden, in Wirklichkeit passiert es nicht so und der Client wird nicht in der Lage, die Ergebnisse zu verarbeiten, bis Alle Nummern wurden generiert.

Die einfache Möglichkeit, den Client vollständig reaktiv zu machen, wäre die Verwendung von WebSockets.

Also, abgesehen von den coolen Sachen (wie schöne Semantik, Zusammensetzung ...), was ist der Punkt der Verwendung von Spring Web Reactive unter Berücksichtigung, dass Browser HTTP-Anfragen nicht reaktiv sind und entsprechen der traditionellen DeferredResult ?

Antwort

15

Es gibt Unterschiede, also lass mich versuchen, es zu brechen.

Für den Rückgabewert DeferredResult<Double[]> muss das Array eindeutig erstellt werden, bevor der Wert in die Antwort geschrieben werden kann.

Spring Web Reactive schreibt jeden einzelnen Wert aus einer Flux<Double>, sobald sie verfügbar ist. Aus der Sicht eines Browsers sehen Sie möglicherweise keinen tatsächlichen Unterschied, da Sie erst dann das vollständige JSON-Array erhalten, wenn es vollständig empfangen wurde.

Dies ist eher eine Frage, wie in einen Browser streamen? Wenn Sie beispielsweise "Accept: text/event-stream" als Anforderungsheader hinzufügen, können Sie jedes Double als einzelnes Ereignis im Browser verwenden. Also ist die Fähigkeit des Servers, es zu tun und es effizient zu tun.

+0

Vielen Dank für die Klärung. In Bezug auf das Streaming, zwei Fragen: 1) Abgesehen von "Text/Event-Stream" aus dem Browser senden, ist es auch notwendig, den Rückgabetyp in der Steuerung von 'Flux ' zu 'Flux ' zu ändern? 2) Für den Fall, dass wir in der Steuerung einen 'Flux ' zurückgeben könnten, würde Jackson Marshalling gelten, nicht wahr? – codependent

+1

Kein Problem. Sowohl "Flux " als auch "Flux " werden unterstützt. Letzteres ist eine Abkürzung für das Erstellen eines SseEvent mit nur Daten. –