Let's imagine a scenario where there's an old app written using Servlet stack and you decide to migrate it to a Spring Webflux. Let's also say that first thing to migrate is RestTemplate
to WebClient
.
What would be preferred way of handling Mono
or Flux
that WebClient
returns? Calling block
seems okay solution since app uses RestTemplate
which blocks anyway. subscribe
should be a bit nicer since it has a callback, but maybe you have to wait to be able to continue. Also, with subscribe
, do we need to handle a Disposable
and, if yes, how, because I'm not sure where is the best place to call dispose
on it?
And one more question regarding JDBC. How dangerous is to use Schedulers.boundedElastic()
? From my understanding, having a separate thread pool should help especially if Netty is used. It's not ideal, but could it be a temporary solution until R2DBC drivers reach 1.0.0? What if app uses Tomcat? Is the situation better since Tomcat by default has more threads?
The main difference between the two frameworks is that spring-mvc is based on thread pools, while spring-webflux is based on event-loop mechanism. Both the models support commonly used annotations such as @Controller . A developer can run a reactive client from a spring-mvc controller to make calls to remote services.
Spring WebFlux allows us to decompose the logic in a declarative way with Mono, Flux, and their rich operator sets. Moreover, we can have functional endpoints besides its @Controller annotated ones, though we can now also use these in Spring MVC.
Spring Webflux does not block a thread to handle each request, because no thread is kept waiting for something to be done (e.g. waiting for an answer from a database). As written in 1., it can be blocked while waiting for an answer from a database or from another service that is called via HTTP.
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.
What would be preferred way of handling Mono or Flux that WebClient returns?
Given you're aiming to use Webflux, the ultimate preferred way is to deal with these publishers the entire way up your reactive chain. This means you won't end up calling subscribe on anything directly, because your controller will itself return a Mono
(and everything, including the WebClient
calls, will just be incorporated into that Mono
via a series of reactive opreations in the chain.)
However, as you point out, you can't realistically migrate everything at once.
If it's only the WebClient
that you're migrating for now, then just call block()
to treat it the same way as your RestController
. There's no advantage with calling subscribe()
and then waiting for the subscription to complete - that's just a less obvious and more long-winded way of blocking.
Once you migrate more and more of your stack to reactive, you can do more and more in a reactive fashion, and then start to "move" your block()
calls further up the chain as a result (until the block is at the controller level, and then you can just switch over to returning the Mono
.)
Also, with subscribe, do we need to handle a Disposable
Only if you need to potentially cancel the subscriber (and it supports it.) This is quite a rare occurance in my experience.
And one more question regarding JDBC. How dangerous is to use
Schedulers.boundedElastic()
?
boundedElastic()
is designed to be a wrapper for blocking IO, so there's nothing inherently wrong with using that on the reactor side. The only "danger" would be on the JDBC / app side as to if it fits your requirements:
If you've got enough long running DB queries that this isn't enough, then you might consider using newBoundedElastic()
instead and specifying the threadCap
and queuedTaskCap
manually.
What if app uses Tomcat? Is the situation better since Tomcat by default has more threads?
I wouldn't advise relying on it. Tomcat still uses one thread per request (even with Webflux), so the danger there is you end up blocking on a thread you shouldn't, and end up not realising and then relying on that behaviour (which would then all come tumbling down when you switched to Netty.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With