Reactive Programming in Spring- Introduction

In this article we will discuss in brief about Reactive Programming and also focus on why the Spring team deprecated the RestTemplate client in favor of the new WebClient introduced as part of Spring 5.

Here is the definition of Reactive Programming from the Spring docs :

Reactive programming is about non-blocking applications that are asynchronous and event-driven and require a small number of threads to scale vertically rather than horizontally

Blocking vs Non-blocking applications:

To understand Non-Blocking applications we will first see an example in the traditional blocking style of writing code

RestTemplate example

Here we are making a call to the URL http://localhost:8081/app/home/{id}. Whenever we hit this endpoint the response comes after 3 seconds which is a delay introduced by me to make the service slow. Here the control flow of the application is blocked until you receive a response from another service . This may not be ideal if you want to make efficient use of your hardware resources and it also affects scalability. Why is that?

Thread Per Request Model in Web applications

In Spring Boot Web applications we have Servlet containers which operate on the Thread per Request model and as each request comes in it assigns the request to a thread and allows it to complete the task. The drawback here is the default thread pool size is 200 and if all your threads are hitting a service which is slow at the moment then they will be in a WAITING state and new incoming requests will get queued up. It is possible to increase the thread pool size from 200 to say 500 but it is going to put a heavy strain on the processor of your application. This issue can be overcome to an extent by Horizontal Scaling.

HORIZONTAL SCALING

Horizontal Scaling is a means by which we can spin up more instances of our Web Application bound to containers like Kubernetes deployed in AWS managed by a Load Balancer . By this way each instance of our application will have the default thread pool size say 200 threads but 5 instances will be running which will give us a thread pool size of 1000 without affecting the memory resources and processing.

Horizontal Scaling using Load Balancer

But still it doesnt solve our problem right? Imagine our application becomes popular worldwide and then we have to spin up more instances and use up more resources all because a slow service is blocking our application.

NON-BLOCKING ASYNCHRONOUS APPLICATIONS:

WebClient was introduced as part of Spring 5 as an alternative to RestTemplate primarily for helping out with Reactive Programming as part of the Spring WebFlux project. Below is an example which does the same thing as above

WebClient initialized with target endpoint URL

Here we are making a call to the same slow service URL http://localhost:8081/app/home/{id}. The output of the above program would be :

Output

Let us analyze the above piece of Code and the terms involved.

MONO

It is an API introduced as part of the Reactive Programming Project which has various methods in order to perform operations on an object that will be received at a future point in time. One can wrap their response object in a Mono.

FLUX

Flux is the same as Mono but we will use Mono to receive a single object whereas if the response received will be a list of values we will wrap it in a flux instead of Mono. Here i have not used Flux to keep things simple.

PUBLISHER-SUBSCRIBER Model

Mono is the publisher and as soon as data is received from the slow service it will stream the data to all of its subscribers . Here in the above example i have explicitly subscribed to the result of a Mono to print out the name . In other cases where the browser hits this particular endpoint the browser automatically becomes a subscriber and Mono API streams the result to the browser whenever the response becomes available.

Reactive Steam Specification details an Event Driven application and in our example the following is the sequence of events which take place after the execution starts:

Publisher / Subscriber Model

Earlier we mentioned that such Reactive Java Web Applications are extremely Scalable and make efficient usage of resources.

Reactive App

In Reactive Application every activity is Event based and the entire application is Event Driven . The above diagram clearly explains how a Thread can never go into a waiting state. So what is the pretty obvious benefit of this? LESSER THREADS!!

The CPU doesnt need to switch between a lot of threads and the thread pool size can always be kept at a bare minimum necessary for that application. This way the load on CPU is also less .

Another crucial advantage of such a programming paradigm is the concept of Backpressure.

BACKPRESSURE

Imagine a case where the web client makes a call to fetch all items from the database in order to do some processing. The Backend API has 1000 results matching that criteria and is ready to return the entire list of items.

Now the Client is not equipped to handle such large processing of data and hence it can say limit your response to 50 at a time. This process is BACKPRESSURE , The Event Driven mechanism allows for such processing to take place as the response is received one event at a time.

Does that mean it is all going to be Reactive going forward ? NO!!!!!

There are certain cases where such a paradigm helps and other cases where it does not.

DISADVANTAGES :

PROCESSING DATA :

Any processing on MONO or FLUX is quite complex and it has to be done with API methods from Reactive stack. Also everything is event driven and based on streams of data which differs from imperative style of programming .

END to END REACTIVE :

The entire stack has to be Reactive including database drivers as these drivers help the database to notify the Publisher whenever it is ready with the data and API calls also has to be Reactive. If at any point in our application we have a blocking piece of code the entire purpose is defeated.

DEBUG :

Debugging becomes difficult and loggers need to be carefully monitored as all activities are event based.

MONOLITH APPS:

Primarily useful in world of Microservices and Distributed Systems. In Monolithic Application it may not be too useful.

Conclusion :

We have barely scratched the surface of Reactive Programming in this article but it will hold you in good stead going forward.

The projects are available in github link HERE

References :

docs.spring.io – The official documentation

Defog Tech – YouTube

Leave a comment