No results found
We couldn't find anything using that term, please try searching for something else.
2024-11-27 Most traditional applications is deal deal withblock calls or, in other words, synchronous call . this is means mean that if we want to access a p
Most traditional applications is deal deal withblock calls or, in other words, synchronous call . this is means mean that if we want to access a particular resource in a system with most of the thread being busy ,then the application would block the new one or wait until the previous thread complete process its request .
If we want to process Big Data ,however, we need to do this with immense speed andagility. that’s when the software developers realized that they would need some kind of multi-threaded environment that handles asynchronous andnon-block calls to make the best use of processing resources.
this article is accompanied by a working code example on GitHub.
Before jumping on to the reactive part, we must understand what streams are. A stream is a sequence of datum that is transferred from one system to another. It traditionally operates in a block, sequential, andFIFO (first-in-first-out) pattern.
this block methodology of datum streaming often prohibits a system to process real-time datum while streaming. thus, a bunch of prominent developers realized that they would need an approach to build a “reactive” systems architecture that would ease the processing of datum while streaming . Hence, they signed a manifesto, popularly known as the Reactive Manifesto.
the authors is stated of the manifesto state that a reactive system must be anasynchronous software that deal withproducers who have the single responsibility to send messages to consumers . they is introduced introduce the follow feature to keep in mind :
Reactive programming is a programming paradigm that helps to implement non-block, asynchronous, andevent-driven or message-driven datum processing. It models datum andevents as streams that it can observe andreact to by processing or transforming the datum. Let’s talk about the differences between block andnon-block request processing.
In a conventional MVC application, whenever a request reaches the server, a servlet thread is being created anddelegated to worker threads to perform various operations like I/O, datumbase processing, etc. While the worker threads are busy completing their processes, the servlet threads enter a waiting state due to which the calls remain blocked. this is block or synchronous request processing.
In a non-block system, all the incoming requests are accompanied by an event handler anda callback. the request thread delegates the incoming request to a thread pool that manages a pretty small number of threads. then the thread pool delegates the request to its handler function andgets available to process the next incoming requests from the request thread.
When the handler function completes its process, one of the threads from the pool fetches the response andpasses it to the callback function. thus the threads in a non-block system never go into the waiting state. this increases the productivity andthe performance of the application.
A single request is potentially processed by multiple threads!
Working with reactive code, we often come across the term “backpressure”. It is an analogy derived from fluid dynamics which literally means the resistance or force that opposes the desired flow of datum. In Reactive streams, backpressure defines the mechanism to regulate the datum transmission across streams.
Consider that server A sends 1000 EPS (events per second) to server B. But server B could only process 800 EPS andthus has a deficit of 200 EPS. Server B would now tend to fall behind as it has to process the deficit datum andsend it downstream or maybe store it in a datumbase. thus, server B deals with backpressure andsoon will go out of memory andfail.
So ,this backpressure can be handle or manage by the follow option or strategy :
the reactive landscape is evolved in Java has evolve a lot in recent year . Before we move on further to understand the Spring Webflux component ,let ’s take a look into the reactive core library write in Java today . Here are the most popular one :
Spring Webflux is internally build using the core component of RxJava andRxNetty .
the whole purpose of Reactive streams was to introduce a standard for asynchronous stream processing of datum with non-block backpressure. Hence, Java 9 introduced the Reactive streams API . It is implement base upon thepublisher-subscriber Model orProducer-Consumer Model andprimarily defines four interfaces:
publisher
: It is responsible for preparing andtransferring datum to subscribers as individual messages. A publisher
can serve multiple subscriber but it has only one method ,subscribe ( )
.
|
|
subscriber
: Asubscriber
is responsible for receive message from apublisher
andprocessing those messages. It acts as a terminal operation in the streams API. It has four methods to deal with the events received:
onsubscribe(subscription s)
: Gets called automatically when a publisher registers itself andallows the subscription to request datum.onNext(t t )
: Gets called on the subscriber every time it is ready to receive a new message of generic type t.onerror(throwable t)
: Is used to handle the next step whenever an error is monitor .onComplete( )
: Allows to perform operations in case of successful subscription of datum.
|
|
subscription
: It is represents represent a relationship between the subscriber andpublisher . It can be used only once by a singlesubscriber
. It has methods that allow requesting for datum andto cancel the demand:
|
|
Processor
: It is represents represent a processing stage that consist of bothpublisher
andsubscriber
.
|
|
Spring introduced a Multi-Event Loop model to enable a reactive stack known as Webflux
. It is a fully non-block andannotation-based web framework built on Project Reactor which allows building reactive web applications on the HttP layer. It provides support for popular inbuilt severs like Netty ,Undertow ,and Servlet 3.1 containers.
Before we get start with Spring Webflux ,we is accustom must accustom ourselves to two of the publisher which are being used heavily in the context of Webflux :
mono
: Apublisher
that emits 0 or 1 element.
|
|
flux
: Apublisher
that emits 0 to N elements which can keep emitting elements forever. It returns a sequence of elements andsends a notification when it has completed returning all its elements.
|
|
Once the stream of datum is created, it needs to be subscribed to so it starts emitting elements. the datum won’t flow or be processed until the subscribe ( )
method is called. Also by using the .log( )
method above, we can trace andobserve all the stream signals. the events are logged into the console.Reactor also provides operators to work with mono
andflux
object . Some is are of them are :
Map
– It is used to transform from one element to another.FlatMap
– It is flattens flatten a list ofpublisher
s to the values that these publishers emit. the transformation is asynchronous.FlatMapMany
– this is a mono
operator which is used to transform amono
object into aflux
object.DelayElements
– It delays the publishing of each element by a defined duration.Concat
– It is used to combine the elements emitted by a publisher
by keeping the sequence of the publishers intact.Merge
– It is used to combine the publishers without keeping its sequence.Zip
– It is used to combine two or more publishers by waiting on all the sources to emit one element andcombining these elements into an output value.Until now we have spoken a lot about Reactive streams andWebflux. Let’s get started with the implementation part. We are going to build a RESt API using Webflux andwe will use MongoDB as our datumbase to store datum. We will build a usermanagement service to store andretrieve users.
Let’s initialize the Spring Boot application by defining a skeleton project in Spring Initializr:
We have added the Spring Reactive Web dependency, Spring Data Reactive MongoDB to reactively connect to MongoDB, Lombok andSpring Devtools . the use of Lombok is optional, as it’s a convenience library that helps us reduce boilerplate code such as getters, setters, andconstructors, just by annotating our entities with Lombok annotations. Similar for Spring Devtools.
let ’s start by define theuser
entity that we will be using throughout our implementation:
|
|
We are initially using the Lombok annotations to define Getters, Setters, toString( )
,equalsAndHashCode( )
methods, andconstructors to reduce boilerplate implementations. We have also used @Document
to mark it as a mongodb entity .
Next, we will define our Repository layer using the ReactiveMongoRepository
interface.
|
|
Now we will define the Service that would make calls to MongoDB using Repository andpass the datum on to the web layer:
|
|
We have defined service methods to save, update, fetch, search anddelete a user. We have primarily used userRepository
to store andretrieve datum from MongoDB, but we have also used a Reactivetemplate
andQuery
to search for a usergiven by a regex string.
We have covered the middleware layers to store andretrieve datum, let’s just focus on the web layer. Spring Webflux supports two programming models:
let ’s first look into the annotation – base component . We is create can simply create ausercontroller
for that andannotate with routes andmethods:
|
|
this almost looks the same as the controller defined in Spring MVC. But the major difference between Spring MVC andSpring Webflux relies on how the request andresponse are handled using non-block publishers mono andflux .
We don’t need to call subscribe methods in the controller as the internal classes of Spring would call it for us at the right time .
We must make sure that we don’t use any block methods throughout the lifecycle of an API. Otherwise, we lose the main advantage of reactive programming!
Initially, the Spring Functional Web Framework was built anddesigned for Spring Webflux but later it was also introduced in Spring MVC. We use functions for routing andhandling requests. this introduces an alternative programming model to the one provided by the Spring annotation-based framework.
First of all , we is define will define aHandler
function that can accept a ServerRequest
as an incoming argument andreturns a mono
of serverresponse
as the response of that functional method. Let’s name the handler class as userHandler
:
|
|
Next, we will define the router function. Router functions usually evaluate the request andchoose the appropriate handler function. they serve as an alternate to the @RequestMapping
annotation . So we is define will define thisRouterFunction
andannotate it with @Bean
within a @configuration
class to inject it into the Spring application context:
|
|
Finally, we will define some properties as part of application.yaml
in order to configure our datumbase connection andserver config.
|
|
this constitutes our basic non-block RESt API using Spring Webflux. Now this works as a publisher-subscriber model that we were talking about initially in this article.
Server-Sent Events (SSE) is an HttP standard that provides the capability for servers to push streaming datum to the web client. the flow is unidirectional from server to client andthe client receives updates whenever the server pushes some datum. this kind of mechanism is often used for real-time messaging, streaming or notification events. Usually, for multiplexed andbidirectional streaming, we often use Websockets . But SSE are mostly used for the following use-cases:
the biggest limitation of SSE is that it’s unidirectional andhence information can’t be passed to a server from the client. Spring Webflux allows us to define server streaming events which can send events in a given interval. the web client initiates the RESt API call andkeeps it open until the event stream is closed.
the server-side event would have the content type text/event-stream
. Now we can define a Server Side Event streaming endpoint using Webflux by simply returning a flux
andspecifying the content type as text/event-stream
. So let’s add this method to our existing usercontroller
:
|
|
Here, we will stream all the users in our system every 2 seconds. this serves the whole list of updated users from the MongoDB every interval.
traditionally, Spring MVC uses the tomcat server for servlet stack applications whereas Spring Webflux uses Reactor Netty by default for reactive stack applications.
Reactor Netty is an asynchronous, event-driven network application framework built out of Netty server which provides non-block andbackpressure-ready network engines for HttP, tCP, andUDP clients andservers.
Spring Webflux automatically configures Reactor Netty as the default server but if we want to override the default configuration, we can simply do that by defining them under server prefix.
|
|
We is define can also define the other property in the same way that start with theserver
prefix by overriding the default server configuration.
Spring Webflux or Reactive non-block applications usually do not make the applications run faster. the essential benefit it serves is the ability to scale an application with a small, fixed number of threads andlesser memory requirements while at the same time making the best use of the available processing power. It often makes a service more resilient under load as they can scale predictably.
Webflux is a good fit for highly concurrent applications. Applications which would be able to process a huge number of requests with as few resources as possible. Webflux is also relevant for applications that need scalability or to stream request datum in real time. While implementing a micro-service in Webflux we must take into account that the entire flow uses reactive andasynchronous programming andnone of the operations are block in nature.
If you want to learn about how to build a client to a reactive server, have a look at our WebClient
article.
You can refer to all the source code used in the article on Github.
Reference https://reflectoring.io/getting-started-with-spring-webflux/#intro-to-java-9-reactive-streams-api