Introducing Spring MVC Async and Spring WebFlux
In this article, I will review Async annotation@ in Spring MVC and then I will meet you with Spring WebFlux. The goal is to better understand the differences between the two frameworks.
In this section, we want to show how to implement a simple Web application with any of these APIs by selecting a scenario. In addition, we will continue to manage Thread and Blocking or Non-blocking input/output (I/O) in each case.
If we select a Web application with an Endpoint, it will return a String as Response. The point is that here the request passes through a filter with a small 200 ms delay, and then Controller needs 500 milliseconds to calculate and restore the result.
Next, we want to simulate Load with Apache ab in both Endpoint and check the app’s behavior with JConsole.
Spring MVC Async
Async annotation@ was introduced by Spring 3.0. Async@ goal is to allow the app to run Heavy-load tasks on a separate Thread. Also, the applicant can wait for the result, so the type of return of the answer should not be of the kind that is throw exception and can be considered any of the future types, CompletableFuture or ListenableFuture.
In addition, Spring 3.2 introduced the org.springframework.web.context.request.async package, which together with Servlet 3.0 adds the Asynchronous process to web layers, so, after Spring 3.2, Async@ can be used in Annotate classes called Controller or RestController.
When the Client starts a request, it passes through filter chains until it reaches DispatcherServlet.
Then, Servlet tries to dispatch requests at the same time. Calling AsyncWebRequest#startAsync mark the request, transfers the processing of requests to WebSyncManager, and finishes without Committ responding. Filter chain also returns to Root in reverse.
But WebAsyncManager sends the application processing job in its associated ExecutorService and notifies DispatcherServlet whenever the result is ready.
Spring Async Implementation
We start Implementation by writing a sample class called AsyncVsWebFluxApp for our program. Here, @EnableAsync does the job of enabling Async for the Spring Boot app:
Then we have AsyncFilter, which implements javax.servlet.Filter. Don’t forget to simulate the delay in the doFilter way:
Finally, we develop our AsyncController with an Endpoint called “/async_result”:
Because of the @Async mentioned in getResultAsync, this method runs on a separate Thread in the program’s default ExecutorService. However, you can set up a specific ExecutorService for your method.
To run the program, install Apache ab or any tool to simulate Load. You can then send a group of Concurrent requests via Endpoint called “async_result”. You can also run JConsole and connect it to your Java app to monitor the process:
Spring 5.0 has introduced the WebFlux platform to support Reactive web in the non-blocking way. WebFlux is another great performance of Reactive stream and based on the Reactor API.
Spring WebFlux supports Reactive backpressure and +Servlet 3.1 with Non-blocking I/O. It can therefore be run on Netty, Undertow, Jetty, Tomcat or any server compatible with +Servlet 3.1.
Although not all servers use thread control and Concurrency control models, Spring WebFlux will work fine as long as it supports Non-blocking I/O and Reactive backpressure.
Spring WebFlux allows you to decompose Logic in the Declarative way with Mono, Flux and their set of operators. In addition, you can also have Functional Endpoints in addition to Controller@ Annotate points, although you can now use these in Spring MVC as well.
Spring WebFlux Implementation
To implement WebFlux, we go according to the same async method, so first, we create AsyncVsWebFluxApp:
Then we need to write our WebFluxFilter program, which implements WebFilter. We will create a deliberate delay and then transfer the request to filter chain:
Finally, we’ll have our own WebFluxController showing an Endpoint called “/flux_result” and <String> returning Mono as the answer:
To test the program, we take the same approach we have applied to our Async sample program:</String>
What is the difference between Spring MVC Async and Spring WebFlux?
Spring Async supports Servlet 3.0, but Spring WebFlux supports +Servlet 3.1. This will cause the following differences:
- The I/O Spring Async model is block-type while communicating with a customer, which may cause performance problems for customers whose communication speed is slower. Spring WebFlux, on the other hand, offers a Non-blocking I/O model.
- Reading the request text or request sections in Spring Async is block type, while it is not the case in Spring WebFlux.
- In Spring Async, filters and Servlets work synchronously, but Spring WebFlux supports quite Asynchronous communication.
- Unlike Spring Async, Spring WebFlux is compatible with a wide range of Web/Application servers such as Netty and Undertow.
In addition to the above, Spring WebFlux supports Reactive backpressure, so we will have more control over MVC Async and Spring MVC. Spring Flux also has the ability to functional programming and decompose Declarative APIs thanks to the Reactor API.
And in the end,
The question is, does all of this lead us to use Spring WebFlux? Spring Async or even Spring MVC may be the right solution for many existing projects, depending on the appropriate scalability load or availability of the system. In the case of Scalability, using Spring Async gives us better results than running synchronous Spring MVC, and Spring WebFlux provides higher Elasticity and Availability due to its Reactive nature.