77

I'm trying to understand Spring WebFlux. The things I've found so far are reactive at the core, no Servlet API, no thread per request, HTTP 2, server pushes, application/stream+json.

But what is the difference between asynchronous calls in Spring MVC? I mean in Spring MVC when you return Future, DefferedResult and etc you get logic in the request handler (controller method) executed in a separate thread, so you can benefit from saving thread pool resources for dispatching requests as well.

So could you please highlight differences related to that? Why WebFlux is better here?

Thank you for your time very much!

Dmitry Senkovich
  • 5,521
  • 8
  • 37
  • 74
  • 5
    Reactive programming is push driven and uses a single dispatcher thread (which is highly efficient) whereas the old model is still limited to the number of threads in your thread pool. – M. Deinum Oct 06 '17 at 12:59
  • @M. Deinum But in this case I'm limited with load one thread can handle. Why not to use several of them, not just one having multicore system? – Dmitry Senkovich Oct 06 '17 at 13:02
  • 2
    It is an event dispatcher thread it is an entirely different model. It only dispatches events (very quickly) whereas the other model is still blocking. – M. Deinum Oct 06 '17 at 13:05
  • @M. Deinum ok, that is very interesting, I'm sure I should take a look at it, thank you! – Dmitry Senkovich Oct 06 '17 at 13:08
  • @M. Deinum, please share request lifecycle – gstackoverflow Jun 04 '19 at 12:53
  • @M. Deinum, spring can work with servlet 3.1 without webflux (completableFuture as a return type + tomcat 8.5+) – gstackoverflow Jun 27 '19 at 23:01

2 Answers2

55

The Servlet async model introduces an async boundary between the container threads (1 Servlet request/thread model) and the processing of the request in your application. Processing can happen on a different thread or wait. In the end, you have to dispatch back to a container thread and read/write in a blocking way (InputStream and OutputStream are inherently blocking APIs).

With that model, you need many threads to achieve concurrency (because many of those can be blocked waiting for I/O). This costs resources and it can be a tradeoff, depending on your use case.

With non-blocking code, you only need a few threads to process a lot of requests concurrently. This is a different concurrency model; like any model, there are benefits and tradeoffs coming with it.

For more information about that comparison, this Servlet vs. Reactive stacks talk should be of interest.

Brian Clozel
  • 56,583
  • 15
  • 167
  • 176
  • From my understanding, another benefit would be what's in the response itself. A Publisher (Flux/Mono) is considered more "advanced" than a Future, as it gives more control on the flow, e.g backpressure etc. – tuan.dinh Mar 12 '19 at 04:52
  • 2
    Could you eleborate? Even for reactive webFlux we have to wait writing to socket. As I understand in case of Asyc servlet api Container thread have to pass request into application threadPool to await free worker and after passing the thread becomes free and can be reused for another requests just after passing that request. Why do you say that **With that model, you need many threads to achieve concurrency** ? – gstackoverflow Jun 25 '19 at 15:19
  • @gstackoverflow We sometimes need to wait to write/read to a socket, but in a non-blocking manner - in that case, no thread is sitting idly during that time. With the Servlet 3.0 model, the number of server threads is proportional to the number of max concurrent requests. Please watch the talk I pointed to, this is all explained there in great details. – Brian Clozel Jun 25 '19 at 15:30
  • I don't see there text version. It is a bit complex for me to watch video in English and understand tricky details. – gstackoverflow Jun 25 '19 at 16:20
  • I didn't get the question properly first but now I understood it. So my question a bit different. Is there any difference between returning DeferredResult from spring controller methods(it leads to using servlet 3 features) and spring webFlux ? – gstackoverflow Jun 27 '19 at 13:18
  • that's exactly the point of my answer. Short version is: non-blocking I/O vs. blocking I/O. – Brian Clozel Jun 27 '19 at 13:23
  • 2
    Sorry, it is not clear for me. In case of DefferedResult Tomcat thread just passes request to application threadPool - it is so short operations and thus it is ready to handle another request. Which killer feature webFlux provides? – gstackoverflow Jun 27 '19 at 13:41
  • 1) you're not blocking a server thread but you're still deferring operations in a threadpool with possible blocking I/O, so that pool can be overwhelmed 2) reading/writing in a blocking manner means that the server thread can get stuck waiting, trying to write to a socket where the client is a slow consumer (e.g. mobile on a bad connection) – Brian Clozel Jun 27 '19 at 13:45
  • 3
    According to your answer I understand that your concern about DefferedResult contains in that phrase: **In the end, you have to dispatch back to a container thread and read/write in a blocking way (InputStream and OutputStream are inherently blocking APIs).** Do you want to say that WebFlux has some magic sockets which can read/write asyncronously ? Is it possible? – gstackoverflow Jun 27 '19 at 13:46
  • In other words in case of DefferedResult the IO is used but in case if WebFlux - NIO ? – gstackoverflow Jun 27 '19 at 14:19
  • As it is mentioned here: https://spring.io/blog/2016/07/20/notes-on-reactive-programming-part-iii-a-simple-http-server-application webflux on tomcat is built over servlet 3.1 – gstackoverflow Jun 27 '19 at 21:51
10

Servlet API is blocking I/O which requires 1 thread per HTTP request. Spring MVC async relies on Servlet APIs which only provides async behavior between container threads and request processing threads but not end to end.

Spring WebFlux on the other hand achieves concurrency by a fixed number of threads by using HTTP sockets and pushing chunks of data at a time through the sockets. This mechanism is called event loop, an idea made popular by Node.js. Such an approach is scalable and resilient. Spring 5's spring-webflux uses the event loop approach to provide async behavior.

More can be read from

Javed Afroz
  • 149
  • 1
  • 7