Spring boot 3 microservices with Spring Cloud Part-2
Introduction
Spring Webflux is a powerful and efficient reactive web framework for building fast, non-blocking and event-driven applications. It is a part of the popular Spring Framework and is designed to handle high concurrency with ease. The main goal of Spring Webflux is to provide a reactive programming model for building web applications, which is becoming increasingly essential in today's fast-paced and data-intensive world.
Spring webflux vs Spring MVC
One of the key differences between Spring Webflux and the traditional Spring MVC framework is the underlying threading model. Spring MVC follows the thread-per-request model, where each request is handled by a dedicated thread from a thread pool. This model has been the standard approach for building web applications for many years. However, with the rise of highly concurrent applications, this model has started to show its limitations. As the number of concurrent requests increases, so does the number of threads, which can lead to performance degradation and resource exhaustion.
On the other hand, Spring Webflux follows a non-blocking, event-driven model that is based on reactive programming principles. Instead of dedicating a thread to each request, webflux uses an event loop to handle all incoming requests. This allows it to handle a large number of concurrent requests with a small and fixed number of threads, making it highly scalable and efficient.
Webflux Model
Each event loop represents a main thread which can process the task. Usually there can be as many event loop as the number of cores in the CPU. When client sends a request it is submitted to the event queue as an event and event loop continue to serve or process these events from the queue in a sequential manner. Once event is submitted to event loop, it register a callback with corresponding data layer either database, or web service call to another service or any other batch task. Here important thing to note is, event loop does not wait for the ongoing task to complete the collect the result, rather it registers a callback and make itself available to process next event.
As soon as the operation complete from the database layer, it will mark the operation complete event and further event loop can trigger callback
The asynchronous and non blocking model of webflux impact all layers of a typical software development . In order to get the maximum benefits of reactive streams, all the sections of the application including client, server and database should follow the reactive streams.
RestTemplate vs WebClient
In order to make a call to a service, restTemlpate is a usual norm in case of spring mvc application. The restTemplate follows synchronous call to service and it block the executing thread until the results retrieved from the call. This blocks the system from performing further operations. WebClient instead, is a reactive and non-blocking HttpClient. It is a part of Spring webflux library and support both synchronous and asynchronous operations.
JDBC vs R2DBC
Standard JDBC driver used to connect the application to the database follows blocking operation and not reactive. The has been made to create a Reactive relational database connectivity. R2DBC driver uses the r2dbc- spi specification for database operation which are fully reactive. As of now following vendors are supporting the r2dbc
PostgresSQL
H2
MicrosoftSQLServer
To understand how Spring Webflux works, let's look at a simple code example. Consider a REST API that returns a list of users from a database. In Spring MVC, the controller method would look something like this:
@GetMapping('/users')
public List getAllUsers() {
List users = userRepository.findAll();
return users;
}
Here, the findAll() method would query the database and return a list of users. However, if this method takes a long time to execute, it can block the thread and prevent it from handling other requests. In contrast, the same functionality in Spring Webflux would look like this:
@GetMapping('/users')
public Flux getAllUsers() {
Flux users = userRepository.findAll();
return users;
}
The key difference here is that the findAll() method now returns a Flux, which is a reactive stream of data. This method does not block the thread and returns the data as and when it becomes available. This allows the thread to handle other requests while the database query is being executed in the background.
Find more about reactive here
public interface ReactiveUserRepository extends ReactiveCrudRepository<User, String> {
Flux<User> findByLastname(Mono<String> lastname);
@Query("{ 'firstname': ?0, 'lastname': ?1}")
Mono<User> findByFirstnameAndLastname(String firstname, String lastname);
}
The ReactiveCrudRepository method the returns reactive objects like Mono<User> or Flux<User>. The repository consist of crud methods provided in a Spring Data provided interface. Also it supports the domain specific sql query methods.
Now, let's take a look at the main interfaces of Spring Webflux:
1. HandlerFunction: This interface is the core of Spring Webflux and is responsible for handling incoming requests. It takes in a ServerRequest and returns a ServerResponse. It is the equivalent of the @Controller annotation in Spring MVC.
2. RouterFunction: This interface is used to map incoming requests to the appropriate handler function. It takes in a ServerRequest and returns a HandlerFunction. It is the equivalent of the @RequestMapping annotation in Spring MVC.
3. WebClient: This interface is used to make HTTP requests to external services. It returns a Flux or Mono (a reactive wrapper for a single element) and allows for non-blocking communication with external systems.
4. ServerRequest: This interface represents an incoming HTTP request and provides access to the request parameters, body, and headers.
5. ServerResponse: This interface represents the response to be sent back to the client. It allows for setting the status code, headers, and body of the response.
Spring Webflux is an excellent choice for building reactive and high-performance web applications. Its non-blocking and event-driven model make it highly scalable and efficient, making it suitable for handling large amounts of data and concurrent requests. With its intuitive interfaces and seamless integration with other Spring components, Webflux is a valuable addition to the Spring ecosystem.