Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC to Spring Webflux migration - block vs subscribe

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?

like image 437
Sven Vidak Avatar asked Oct 22 '19 22:10

Sven Vidak


People also ask

What is the difference between Spring MVC and Spring WebFlux?

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.

What are the advantages of WebFlux?

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.

Why WebFlux is non-blocking?

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.

When should we use spring WebFlux?

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.


Video Answer


1 Answers

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:

  • It's capped at 10x the number of CPU cores
  • The number of "queued" tasks is capped at 100K

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.)

like image 72
Michael Berry Avatar answered Sep 20 '22 03:09

Michael Berry