Introduction
Reactive Microservices are built following the reactive manifesto. It defines four core concepts and mandates reactive systems to be Responsive, Resilient, Elastic, and Message Driven. Reactive programming is implemented using Observables and event Publisher/Subscriber and works on Asynchronous Data Streams. Using a reactive programming method does not mean that the system is reactive. It can only be an enabler and is not a requirement.
Responsive
A system is responsive when it responds to requests promptly. In Microservices, we should optimally use the processing and I/O resources to satisfy this property. This scenario is addressed by using non-blocking I/O with asynchronous programming.
Resilient
The resilience of a system is where it should still respond in the event of possible failures in execution. We should expect failures and take proactive measures in handling them in architecture and design. Some of the methods used to bring resiliency are Circuit Breaker, Load Balancing, Failover, Retry, and Timeouts.
Elastic
The elasticity is the ability to spin up new instances of services and remove instances of services when the load goes down. With the emergence of cloud computing platforms like AWS, Azure, and GCP these services have become a commodity now. This has been accelerated with the adoption of container-based technologies like Docker, and container orchestration systems like Kubernetes. Kubernetes has become the de-facto standard in container management. Due to its common API in creating deployments, the same application can be deployed in any Kubernetes-supported cloud platforms such as AKS, EKS, and GKE.
Message Driven
Microservices communications are handled through REST interface or message passing. A RESTful interface is used if functionality needs a strict request/response synchronous execution. If not, the preferred approach is to have a message-driven system. This provides loose coupling, isolation, and better resilience against failures. With this approach, future extensions of the system such as adding new services that consume an existing service can be done without downtime and redeploying any of the existing services in the system.
Evaluation of Microservices
What is Reactive Manifesto?
Reactive Manifesto is a document that defines the 4 core principles of reactive programming, It says every reactive system should be Responsive, Resilient, Elastic, and Message Driven.
A responsive application is the primary goal of reactive architecture. For an application to become responsive, it should be scalable and resilient. A message-driven architecture is the backbone of scalable, resilient, and responsive systems. A reactive should satisfy all the four principles we discussed above.
TERMINOLOGY OF REACTIVE THINGS
Reactive Principles
Stay Responsive – Says that a reactive system should always be responsive to user inputs and updates
Accept Uncertainty & Embrace Failure
Reactive systems should have the capability to act upon any uncertainty and should have the capability to self-heal after a failure. This can be achieved in a reactive system by adding monitoring services and container management tools like Kubernetes.
Assert Autonomy
Reactive system should be self-contained and work autonomously.
Tailor Consistency
When we go for a distributed system one of the major challenges we may face is the eventual consistency of the transactions. In a Reactive Microservice system, we can achieve this by introducing CQRS Pattern and Event Sourcing. Another way is to use SAGA Pattern with Choreography or Orchestration.
Decouple Time & Decouple Space
Reactive systems should work in Asynchronous Time and Asynchronous Space.
Handle Dynamics
Reactive system should be capable enough to scale up and down automatically as per the need.
Reactive Components
Reactive Streams: Reactive system works on synchronous reactive data streams. Data flows from source to destination and vice versa as streams.
Publishers & Subscribers: Asynchronous message broker is an integral part for message passing between the services and layers in a reactive system and uses the Publisher/Subscriber mechanism to send and receive messages.
Reactive Architecture
Reactive systems are built by combining an Event Driven Architecture and Microservices Architecture
Reactive Programming Paradigm
As a programming paradigm for building reactive systems, reactive programming emphasizes formulating asynchronous programming logic as data streams, and automatic propagation of changes to values of correlated variables in the system. The languages used for such a programming paradigm would provide suitable composable functions to operate on the formulated streams.
Reactive Streams
Reactive streams are the backbone of a reactive system. Rather than acting on data at rest, reactive systems operate on data in near real-time. Big data is less important than fast data, and fast data is crucial to fast knowledge
Reactive Software
Reactive software is designed and developed using reactive programming, which reacts to user inputs.
Types of Microservices
• Synchronous Microservices
• Asynchronous Microservices
• Reactive Microservices
• Sharded Reactive Microservices
Synchronous Microservices
When we started decomposing the monolith systems into Microservices we would have started with synchronous Microservices. In a synchronous Microservice, all the components are synchronously integrated and the communication between the Microservices and the layers inside the Microservices are synchronous. Every synchronous Microservice maintains its own state and data.
Some of the Cons of Synchronous Microservices are:
• Failure Blocks System
• Poor user experience
• Caller is blocked until the response is received
Synchronous Microservices with BFF
Synchronous Microservices with Event-based DDD
Asynchronous Microservices:
Asynchronous Microservices are services that are asynchronously integrated. They are self-contained and isolated, which means the data owned by that service will be contained inside that Microservice itself. The data communication in these types of services happens through an asynchronous message broker. These Microservices are isolated, autonomous, and self-contained. They are resilient and elastic too; which means during any failure we can have some mechanism to identify and self-heal the system. Logging and Monitoring tool and Circuit breaker are useful to do this. The services are capable of scaling up or scaling down automatically according to the load.
Some of the cons of the services are the message broker is a single point of failure in this service. Suppose if the message broker goes down the entire system will go down.
Another con of this service is the consistency of the transaction if you are doing a distributor transaction that spans to multiple services. To make sure that the system is consistent we can use patterns like SAGA or Event Sourcing with CQRS
Reactive Microservices
The backbone of a reactive Microservice is asynchronous data streams, which flow from the source to the destination. as an asynchronous data streams. For eventual consistency, we need to either introduce Event Sourcing and CQRS pattern or Saga pattern with choreography or orchestration model. Legacy system integration is much easier wherein we can connect the Legacy system to a message broker. We can collect the changes in that Legacy system through (CDC) Change Data Capture. This change will be updated in the stream and whoever subscribed to that topic will receive the data. Reactive systems support reactive stream back pressure. This means, if one service is sending data continuously to another service and the other service is not ready to receive that much data the second service can tell the first service that it cannot process this much data at this time and it should only send a specified amount of data, so that there will not be any clogging or bottleneck between the services.
Some of the cons of these types of Microservices are: complex to design mainly because it contains a lot of moving parts to build the system. To make it reactive we need to add reactive extensions also into the framework. Designing such a system with an asynchronous data stream increases memory usage because the message broker may have to retain the data for later processing. Designing and developing these services required a steep learning curve. These Microservices can be used when your system needs to handle huge data volume.
Sharded Reactive Microservices
Sharded Reactive Microservices are like Reactive Microservice only difference is that we have introduced shards of Microservices. Instead of keeping all the Microservices in a single block, we split them according to some filters. Suppose we want to direct all the traffic according to usernames or geography we can design the shards accordingly.
Sharded Microservice design requires an asynchronous message broker which is partitioned so that according to the filtering logic, the data flows through the specified partition only. These types of Microservices are like Bulletproof systems because they can handle huge data volumes. They are ultra-responsive, resilient, and scalable and the communications between the services are through asynchronous broker. So, it satisfies all the principles said in the reactive manifesto.
Similar to Reactive Microservices, these services are complex to design, and their memory usage may be high. These types of Microservices can be used when your system needs to handle a huge volume of data and if you want to filter the data flow geographically.
Reactive Extensions (Rx) and Tech Stacks
Here are the key areas in code to build reactive microservices
The reactive-stack web framework, Spring WebFlux, was added later in version 5.0. It is fully non-blocking, supports Reactive Streams back pressure, and runs on such servers as Netty, Undertow, and Servlet containers.
Springboot webflux dependency in pom
Here is one example to generate data using webflux
Adding Router in imperative programming structure
Spring introduced functional style in the 5.x era. Utilize with the new RouterFunction, you can handle your web requests in a series of fluent APIs instead of writing a @RestController.
CONCLUSION
The Reactive Microservices has revolutionized the way we build systems, making them more scalable, agile, and resilient. Organizations are increasingly utilizing reactive Microservices seeing their merit over the complexities.
The concept of going reactive is not new, with its roots dating back to the 1970s. However, it is only in the last few years that new tools and technologies have enabled developers to transform the concept into reality by efficiently combining complicated activities.
Many modern programs are reactive in that they respond to events as they occur and do calculations in response and enable users to acquire accurate results more rapidly. Thus, users strengthen their relationship with the system and improve their interaction.
The modern web’s future is reactive in light of Multicore, Blockchain, Cloud and Mobile architectures. Business behemoths such as Netflix, Slack, Microsoft, and Facebook have already begun powering themselves reactively, with many more enterprises following suit.
In short, Microservices have enabled us to create systems that are more user-friendly, reliable, and cost-effective than ever before. The Reactive Revolution is an ongoing process of innovation that will continue to benefit organizations and users worldwide.