Javarevisited

A humble place to learn Java and Programming better.

Reactive Programming in Java

--

Reactive programming is a new paradigm that was introduced recently. Nowadays reactive programming has become a very popular topic among lots of software engineers. Before going forward let's look what is the reason for the popularity of this new paradigm. let's discuss how life was before this reactive programming was introduced.

Traditional way

Let's get a traditional web application backend that was developed without using a reactive way.

As shown in the image above, the backend is hosted in a webserver. When a request comes, it will be assigned to a particular thread by the webserver. and then that thread will be occupied to that request until that request finishes the process. that process may be calling a database or calling a 3rd party API which takes some time to complete. Until that request completes its process, that thread will be busy and cannot be used by another request.

If another request comes, that request will be assigned to another available thread and that thread will also be busy until that request completes its process

Also, there is a maximum thread count for a particular web server and that count may depend based on the webserver. if we use the spring-boot, the webserver container will be tomcat and that container will have 200 maximum threads.

We can see many drawbacks here

Drawbacks in the traditional way

  • Once a thread was assigned to a request that thread won’t be available until that request finishes its process.
  • If all the threads were occupied next requests that come to the server will have to wait until at least one thread will become available.
  • when all the threads are busy, that will degrade the performance of the server because all the memory will be used by all the threads.

As a solution to the above drawbacks, a team of developers, led by Jonas Boner came together and introduced a new programming paradigm. actually, it was a set of core principals

Reactive Programming

Let's understand the meaning of reactive in order to understand the reactive programming paradigm. React means a form of response, but for what do we react? we react to some events. that means reactive is some kind of a response to an event. In that way, we can define reactive programming as an event-driven method of programming.

reactive programming is a programming paradigm where the focus is on developing asynchronous and non-blocking applications in an event-driven form

  • Asynchronous and non-blocking
    Asynchronous execution is a way of executing code without the top-down flow of the code. in a synchronous way, if some blocking call like calling database or calling 3rd party API which may take time, is happening, the execution flow will be blocked. But in a non-blocking and asynchronous way, the execution flow will not be blocked. Rather than that, Futures and callbacks will be used in asynchronous code execution.
  • Event/Message Driven stream data flow
    In reactive programming, data will flow like a stream and because it is reactive, that means there will be an event and response message to that event. In java, it is almost the same as java streams introduced in java 1.8. In the traditional way when we get data from a data source (Eg: database, API), all the data will be fetched at once. but in the event-driven stream, all the data will be fetched one by one and also data will be fetched as an event to the consumer.
  • Functional style code
    In java, there is a concept that functional way of programming. In java, we can write lambda expressions. lambda expressions are functional style codes. In reactive programming in java, we mostly use that lambda expression style.
  • Back Pressure
    In reactive streams when a reactive application(Consumer) is consuming data from the Producer, the producer will publish data to the application continuously as a stream. Sometimes the application cannot process the data at the speed of the producer. in that case, the consumer can notify the producer to slow down the data publishing.

Reactive Streams Specification

It is a set of rules or set of specifications that need to follow when designing a reactive stream. Some software engineers of well-reputed companies like Netflix, Twitter, etc got together and introduced these specifications.

In these specifications, it introduces four interfaces that should be used and overridden when creating a reactive stream.

  • Publisher
    This is a single method interface that will be used to register the subscriber to the publisher. The subscribe method of this interface accepts the subscriber object and registers it.
  • Subscriber
    This is an interface that has four methods
    onSubscribe method will be called by the publisher when subscribing to the Subscribe object.
    onNext method will be called when the next data will be published to the subscriber
    onError method will be called when exceptions arise while publishing data to the subscriber
    onComplete method will be called when successfully complete the data publishing to the subscriber
  • Subscription
    This is an interface with two methods. The subscription object will be created when the subscriber subscribes to the publisher in the publisher object as discussed earlier. then that subscription object will be passed to the subscriber object via onSubscribe method
    request method will be called when the subscriber needs to request n amount of data from the publisher
    cancel method will be called when the subscriber needs to cancel and close the subscription
  • Processor
    This is an interface that is extended by both publisher and subscriber interfaces. this interface is not very common but will be used to process the logic of the subscribing and publishing workflow

Reactive Libraries

A reactive library is nothing but the implementation of reactive specification interfaces which we discussed above. There are some reactive libraries available to us

  • RxJava
  • Project Reactor
  • Flow class in JDK 9

Reactive streams in spring-boot have been developed based on the project reactor.
Because this is java reactive programming, I will discuss a little bit about project reactor main concepts

Project Reactor

Project reactor is one of the main popular reactive libraries in java. Because this is a reactive library, this is a fully non-blocking reactive stream with backpressure supported. this integrates directly with the Java 8 functional APIs. The main artifact of that project reactor is reactor-core, and there are some concepts to be discussed in that reactor core.

Flux

Flux represents an Asynchronous Sequence of 0-N Items. this is like a stream of 0 to N items, and we can do various transformations to this 0-N item stream and also can be transformed to entirely different types of 0-N item stream.

As shown in the image, the top side numbers are the N items which was published by the publisher to the subscriber. It is a type of Flux item stream and the last line represents the completion of that flux stream. The operator box represents the transform operation on that flux stream.

That transformation operation will be applied to the items of flux stream one by one and that is the onNext() method that we discussed earlier section. The bottom set of numbers represents the flux stream that was emitted after applying the transformation.

The red X icon represents some error that happened when applying the transformation to that particular item in that flux stream and that is the onError() method that we discussed earlier in section

If no error happened the transformation will be applied to all the elements and that is the onComplete() method that we discussed earlier section.

Mono

Mono represents only on value stream of items. It consists of only one item. we can do various transformations to this one item stream or can be transformed entirely different one.

As shown in the image only one item will be published by the publisher to the subscriber. it is a type of Mono stream and the last line represents the completion of that Mono stream. The operator box represents the transform operation on that Mono stream.

That transformation operation will be applied to the item of Mono stream and that is the onNext() method that we discussed earlier section.

The red X icon represents some error that happened when applying the transformation to that one item in that Mono stream and that is the onError() method that we discussed earlier in section

If no error happened, the transformation will be applied to the item successfully and that is the onComplete() method that we discussed earlier section.

Performance Experiment

In order to examine the performance, The best way to do that is to compare the Reactive way and the Non-Reactive Way. The experiment is as follows

I create two spring-boot services with one endpoint for each, one with reactive spring web flux and another one with normal spring-boot. Also, I created a Nodejs application in order to call those service endpoints asynchronously.

You can see and play around with the code that I used for this from here in Github
Nodejs API Caller
Reactive Springboot Service
Non Reactive Springboot Service

1st Experiment

In this 1st experiment first I ran the reactive service and then call that endpoint with 10, 100, 1000, 5000, 10000 number requests and record the average time to complete each request and also time to complete all the requests. Then I did the same for non-reactive service as well. Then I created some graphs based on that data

Average time to complete each request graphs

In here INF means 10000 requests cannot be handled the service in my machine due to limited resources, so I assume that is the infinity.

Here we can observe it takes very much the same time that takes by one request to complete its process in a lower number of concurrent requests by both services, but we can see a large difference when it comes to a higher number of concurrent requests. That means this reactive approach is very useful for the applications that will be used by a large number of users at the same time

Time to complete all the requests graphs

In here INF means 10000 requests cannot be handled the service in my machine due to limited resources, so I assume that is the infinity.

Here we can observe it takes very much the same time to take to complete all the processes in a lower number of concurrent requests by both services, but we can see a large difference when it comes to a higher number of concurrent requests. That means this reactive approach is very useful for the applications that will be used by a large number of users at the same time. It saves memory by completing all the processes in less time, so upcoming requests can be utilized without delay and failures.

2nd Experiment

In this 2nd experiment, I will test both services with 1000 concurrent requests, but in this time I will experiment with different delays that may take to complete the process by each service. I will record the time that may take to complete all the requests by each service as well as the average time to complete one request by each service. those delays are 1sec, 5sec, 10sec, 15sec, 20sec. After that, I created some graphs based on that data.

Average time to complete each request graphs

Here we can observe the is a quite big difference in the average time between the reactive way and the nonreactive way to complete one request. In a reactive way, it takes very much less time to complete one request, which may lead us to confirm that the reactive way is the best approach to develop the applications which may handle heavy processes and time-consuming tasks or time-consuming API calls.

Time to complete all the requests graphs

Here we can observe the is a large difference in the time between the reactive way and the nonreactive way to complete heavy time-consuming tasks. In a reactive way, it takes very much less time to complete a bulk of time-consuming tasks. It saves memory by completing all the processes in less time, so upcoming requests can be utilized without delay and failures.

When to use Reactive Programming

  • When you build a web app that will be going to use frequently as well as by many users at the same time. If we use the traditional way, all the threads of the webserver will be busy and your app will become too unresponsive. So the reactive approach is the best solution for these kinds of apps.
  • When you are building a data streaming application. In this application, the data will flow in all the time. For these kinds of applications reactive approach is good.
  • When you are building big data and microservices applications. in Big data applications, lots of data will flow through the app, and in microservices usually, the communications between services are happening through streams, so a reactive approach is good for these kinds of applications.

References

https://projectreactor.io/

--

--

Javarevisited
Javarevisited

Published in Javarevisited

A humble place to learn Java and Programming better.

Jayamal Jayamaha
Jayamal Jayamaha

Written by Jayamal Jayamaha

A boy who loves to explore all the sciences

Responses (1)