Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice when using subscribeOn and publishOn

I’m using Project Reactor for new service I’m writing. I’m using Spring 5 with Netty. I’m interacting with a bunch of different services and relational database. All of these services have a client that is blocking and JDBC is also blocking. So essentially none of these network calls return publisher.

My question is what should be the best practice when working with all blocking API. Currently what I’ve done is wrapped all blocking API code into Mono.callable and used subscribeOn(Scheduler.elastic()). So essentially all the blocking work is done on an elastic thread pool.

Question 1. Shall I create a dedicated thread pool executor rather than using elastic? If yes, then why? Or shall I create a dedicate elastic pool for each of different service?

Question 2. When blocking method return result, shall I use publishOn so that main thread picks up processing again? If yes, how can I get main thread (netty event loop thread?) reference back?

Question 3. If I’m calling multiple blocking calls in multiple different operators (some while chaining, some while using zip() call) then using subscribe publish and again subscribe publish wouldn’t make a lot of context switching?

Most of these questions are related to what should be the best practices.

like image 203
User5817351 Avatar asked Mar 03 '19 00:03

User5817351


People also ask

What is the purpose of publishOn () method?

The publishOn() methodIt takes signals from upstream and replays them downstream while executing the callback on a worker from the associated Scheduler.

Is Spring WebFlux multithreaded?

Spring WebFlux offers a mechanism to switch processing to a different thread pool in between a data flow chain. This can provide us with precise control over the scheduling strategy that we want for certain tasks.

How does Spring WebFlux work internally?

Spring WebFlux internally uses Project Reactor and its publisher implementations, Flux and Mono. The new framework supports two programming models: Annotation-based reactive components. Functional routing and handling.

What is event loop in reactive programming?

In computer science, the event loop is a programming construct or design pattern that waits for and dispatches events or messages in a program.


2 Answers

Most of these questions are related to what should be the best practices.

Reactive Java is still very much in its infancy, so accepted "best practices" are hard to find (the community at large has yet to form a consensus in most cases, so there's just bits of guidance from the reactor development team and a few others.)

That being said, I think there's now some reasonably widely accepted points that will help here. First off, you state:

All of these services have a client that is blocking.

This may be the easiest point, as if you're not interacting with a substantial number of other services that are also non-blocking, there's very little point in using reactor at all. The exception would be if you have a clear migration path to rewrite these services as non-blocking.

JDBC is also blocking

R2DBC isn't, and could be worth investigating (though it's still very early days for that project.)

Shall I create a dedicated thread pool executor rather than using elastic?

There's no need. (The only reason the answer would be "yes" is if you had very specific threading requirements that required specific "tuning" of that executor service, but if that was the case, you wouldn't be asking the question.)

Consider boundedElastic() instead however, as that places a cap on the number of active threads in the scheduler which can reduce runaway numbers of threads creating backpressure issues. This scheduler has been specifically designed to interface to legacy, blocking IO libraries.

shall I create a dedicate elastic pool for each of different service?

Not unless you have a particular reason to. This would be more relevant in a boundedElastic() scheduler if you wanted a separate (or different) bound for different services. (Just creating one so you can "give it a relevant name" is not a good enough reason IMHO.)

When blocking method return result, shall I use publishOn so that main thread picks up processing again?

This is entirely dependant on your use case - reactor is deliberately concurrency agnostic, so it depends whether you need to publish the result in the "main thread" or not. (In my experience, usually you don't care.)

how can I get main thread reference back?

publishOn(Schedulers.immediate()) can be used to publish on the current thread you're calling from.

If I’m calling multiple blocking calls in multiple different operators (some while chaining, some while using zip() call) then using subscribe publish and again subscribe publish wouldn’t make a lot of context switching?

It depends. But yes, certainly potentially - which loops right back to my first point. Unless your time spent in non-blocking code outweighs the time spent calling blocking services in a threadpool, there's very little motivation to switch (unless you plan a gradual migration of services to non-blocking when the core is in place.)

You certainly won't get a performance enhancement from just switching to reactor and using it as a front-end to blocking services wrapped in thread pools.

like image 121
Michael Berry Avatar answered Nov 23 '22 10:11

Michael Berry


I'm not really sure about the benefits you can possibly obtain by using WebFlux in your specific case since all your endpoint services are blocking.

1: Basically you should make a decision based on your specific hardware and the target behavior. As comes from the official docs, Java Reactor is concurrency-agnostic. That means you feel free to use any concurrency or not to use it at all. As far as I know, elastic pool uses plain ExecutorService under the hood. I guess you should make a decision based on your specific hardware, too many context switching and threads is not good from the perfomance point of view, specifically if you have not enough processors

2: Basically no, depends on which behavior you need.

3: You should make yourself more clear, I don't understand why you call such a chain of publish-subscribe.

like image 33
Alex Sergeenko Avatar answered Nov 23 '22 09:11

Alex Sergeenko