top of page
  • Writer's pictureFusionpact

Reactive Architecture - A complete guide

Updated: May 16, 2023



Overview

You probably see the term ‘Microservices’ get thrown around a lot now in Software developer communities. The modern-day user base has very challenging demands, with users bouncing from one application to another if the applications are having a low uptime. The users demand the application to be responsive and resilient all the time.


In this article, I am going to explain to you everything about reactive architecture, and reactive programming and why they are so popular among developers in today’s time.



  1. What is Reactive Architecture?

  2. What are Reactive Principles?

  3. Why Reactive

  4. Reactive Programming v Reactive Architecture

  5. The Actor Model

  6. How to build Microservices?

  7. What are Microservices?


What is Reactive Architecture?

Reactive Architecture is a software design approach that focuses on building applications that are Resilient, Responsive, Elastic, and Message-Driven. These are the four pillars upon which the architecture has been set up. Now, we are going to look at what these four pillars mean.


What are Reactive Principles?



For the course of this blog, we are going to take an example of a demo Flight-booking application which lets users book their flights, hotels, and buses, and provides holiday packages. This application is made up of several services such as LogIn/SignUp, Flight schedules, etc., and their separate databases. Each service has its API. Now if there is a service that wants to leverage the resources of another service, they interact with the help of their APIs.


An application will be called Resilient if the application is still functioning even if it encounters any failures. Now imagine in our demo application if our service of booking flights is down and there is a user who wants to book a hotel for himself, he or she should be able to do that, right? Just because one service of our application is not functional, should not affect other services. Some key concepts that contribute to the resilience of microservices are


Reseliency in reactive architecture
this shows the features of reselient software

  1. Self-healing: Microservices should be designed with self-healing mechanisms in place, such as automatic restart or failover, to ensure that the system continues to function even in the face of failures.

  2. Fault tolerance: Microservices should be designed to be fault-tolerant, meaning that they should be able to continue functioning even when faced with failures or errors. This can be achieved by using techniques such as redundancy, load balancing, and circuit breakers.

  3. Degraded mode operation: Microservices should be designed to continue functioning in a degraded mode even when faced with failures, rather than failing completely. This can help to minimize the impact of failures on the overall system.

  4. Monitoring and observability: Monitoring and observability tools should be integrated into the microservices architecture to allow organizations to quickly detect and respond to failures or other issues.


5.Graceful degradation: Microservices should be designed to degrade gracefully, meaning that they should continue to function in a reduced capacity even when faced with failures or other issues. This can help to minimize the impact of failures on the overall system.


The second pillar of reactive architecture is Responsiveness, this means that an application has to provide a seamless experience to the user, it has to quickly respond to changes in input or load, and delivers the output with minimal latency. Imagine you encounter an application that is experiencing latency issues, maybe it is because it is getting high traffic and the application is taking a long time to respond to user queries that are called an unresponsive application and it usually paves the way for a bad user experience and no business wants that. The goal of the application being responsive is that it is always up and running.


Reactive Systems are also Elastic. What this means is that an application should have the ability to scale up when required and the ability to scale down as well. For example: In the holiday season there is usually huge traffic attracted by our demo application. Hence, there is a need to scale up so that we can manage the load created by the extra traffic and the system remains responsive and resilience but what about after the holiday season, the extra resources that we have leveraged for scaling up are no longer required hence our application must also have the ability to scale down. This is what is meant by elasticity, the application must be flexible enough to meet the increasing and decreasing user base without compromising the responsiveness and resiliency of the application.


An application should also be Message-driven. In terms of our demo application, this means that if a person is looking for flights at the same time he or she should also be able to access the different parts of the application as well at the same time. This is possible through Asynchronous and non-blocking messages. This helps preserve the responsiveness and resiliency of the application.


Why Reactive?

Why should anyone develop microservices for their application reactively?

The answer is pretty simple, our users want to engage with an application that is fast and efficient, has very less load time, and is never down.


All these requirements of the user can only be met if our developers incorporate the Reactive Approach to the software design of Microservices.


Reactive Systems V Reactive Programming


Reactive Programming v Reactive Architecture

If you made till here then you must have got a good grasp gotten a good knowledge about what reactive systems are and how they are they advantageous. A term often gets confused with reactive systems and reactive programming.


Reactive systems and reactive programming are related but distinct concepts.


Reactive systems are software systems that are designed to be responsive, resilient, scalable, and message-driven. They are built using the principles of reactive architecture, which aims to provide a more flexible, efficient, and robust way to build applications that can handle changing conditions and scale dynamically.


Reactive programming, on the other hand, is a programming paradigm that focuses on asynchronous data streams and the propagation of change. It enables developers to build applications that can react to changes in real time, making it a key component of reactive systems.


In other words, reactive programming is a means to an end - it's a way to build reactive systems. Reactive systems are the end goal - they're the systems that are designed to be responsive, resilient, scalable, and message-driven.


In summary, reactive systems are systems that are designed to be reactive, while reactive programming is the programming paradigm that enables the creation of such systems.


The Actor Model


There are several reactive programming techniques used to build reactive applications. One of the most popular paradigms for building concurrent and scalable systems in reactive programming is the Actor Model.


The Actor Model is based on the idea of actors, which are autonomous and concurrent objects that can process messages and perform actions. Actors interact with one another by sending and receiving messages, and they can be used to represent entities such as users, processes, and devices.


In the Actor Model, each actor has its mailbox, which is used to store incoming messages. When an actor receives a message, it processes it and can choose to send messages to other actors. Actors are isolated from one another and can only interact through message passing, which helps to simplify concurrency and make it easier to reason about the behavior of the system.


The Actor Model is used in reactive programming because it provides a way to build scalable, fault-tolerant, and concurrent systems that can handle large amounts of data and handle changing conditions. It is especially well-suited for building large-scale, distributed systems, where actors can be deployed on different nodes and interact with one another over a network.


Overall, the Actor Model is a powerful technique for building reactive systems, providing a simple and intuitive way to model and manage concurrency and interactions between components.


Lightbend Akka is an open-source toolkit for building concurrent and distributed applications in the JVM. It uses the Actor Model as the foundation for building scalable, fault-tolerant systems, and provides a rich set of tools and libraries for building reactive applications.


How to build reactive microservices?


How to build microservices?
flowchart for how to build microservices


This section will tell you all about the different software patterns used to build microservices

  1. Domain Driven Design (DDD)

  2. Hexagonal Architecture

Domain Driven Design


Domain-Driven Design (DDD) is an approach to software development that focuses on modeling the real-world entities and processes that make up a particular business domain. The goal of DDD is to create a software system that accurately reflects the complex business logic and requirements of a particular domain, making it easier to understand and maintain over time.

DDD is based on the idea that software systems should be designed around the concepts and behaviors of the real-world domain they represent, rather than being driven by the technology being used to build the system. To achieve this, DDD introduces several techniques for modeling and organizing software systems, including:


  1. Bounded Contexts: A bounded context is a specific area of the business domain that has a clear and distinct meaning. Bounded contexts help to define the scope of the software system and the relationships between different parts of the domain.

  2. Aggregates: An aggregate is a cluster of related objects that are treated as a single unit. Aggregates are used to model complex business logic and help to ensure consistency and integrity in the domain.

  3. Entities: Entities represent the key concepts in the business domain and have a unique identity. They are used to model the persistent state of the system.

  4. Value Objects: Value objects are objects that represent values or attributes of the business domain and have no identity. They are used to model the non-persistent state of the system.

  5. Services: Services are objects that represent operations that are not naturally associated with any particular entity or value object. They are used to encapsulate complex business logic and interactions between entities.


DDD is a holistic approach to software development that involves not only the design of the code, but also the design of the overall software architecture, the processes and practices used by the development team, and the relationships between stakeholders and the business domain.

By adopting DDD, organizations can create software systems that accurately reflect the complexity of the business domain and can evolve to meet changing business requirements. This results in systems that are more maintainable, understandable, and flexible, and that can deliver real value to the business.


Hexagonal Architecture

Another very popular approach for building microservices is known as Hexagonal Architecture.


Hexagonal Architecture, also known as "Ports and Adapters" or "Onion Architecture," is a software design pattern that emphasizes the separation of concerns in a software system. The idea behind Hexagonal Architecture is to isolate the core functionality of a system from its external dependencies and user interfaces, creating a clean and flexible architecture that can be easily tested and maintained.


The key features of Hexagonal Architecture are:

  1. Core: The core of the system is the heart of the application and contains the business logic and domain model. The core should be isolated from external dependencies and should not know the specific technologies used to implement the system.

  2. Adapters: Adapters are components that translate the inputs and outputs of the core to and from external dependencies, such as databases, web services, and user interfaces. The adapters provide the necessary "glue" between the core and its external dependencies.

  3. Ports: Ports are the interface points between the core and its adapters, defining the inputs and outputs of the core. Ports allow the core to interact with its adapters in a standardized way, regardless of the specific technology used by the adapters.


The main benefit of Hexagonal Architecture is that it creates a clean separation between the core of the system and its external dependencies, making it easier to understand and maintain the system over time. This separation also makes it easier to test the system, as the core can be tested in isolation from the adapters, reducing the number of dependencies that need to be tested.


Hexagonal Architecture is a flexible and adaptable approach to software design that can be used to create systems of any size and complexity, and that can be easily adapted to changing requirements over time. By using Hexagonal Architecture, organizations can create systems that are scalable, maintainable, and deliver real value to the business.


What are Microservices?

This section will tell you everything there is to know about microservices and some additional principles to keep in mind while developing microservices.

  1. Definition

  2. Principles of Isolation

  3. Isolation Techniques


Definition


By now, you must have a pretty good grasp of reactive systems. Throughout this blog, we have mentioned microservices a few times.

Microservices refer to the pattern of decomposing an application into several small, independent, and loosely coupled services. This software pattern allows its services to be isolated and work independently. Each service can interact with another service through their APIs


Principles of Isolation

These services are isolated from each other by following certain principles of isolation such as :

  1. Isolation of state: Each microservice should manage its state and should not share the state with other microservices. This helps to ensure that changes to one microservice do not affect the state of other microservices.

  2. Isolation of time: Each microservice should operate independently of other microservices and should not have dependencies on the timing of other microservices. This helps to ensure that the operation of one microservice is not affected by the timing of other microservices.

  3. Isolation of space: Each microservice should operate independently of other microservices and should not have dependencies on the location of other microservices. This helps to ensure that the operation of one microservice is not affected by the location of other microservices.

  4. Isolation of failure: Each microservice should be designed to fail independently, without affecting the operation of other microservices. This helps to ensure that a failure in one microservice does not cause a cascading failure in other microservices.


Isolation Techniques

These are some of the techniques which are followed to ensure that the microservices are operating independently.

  1. Isolation of state: Each microservice should manage its state and should not share the state with other microservices. This helps to ensure that changes to one microservice do not affect the state of other microservices.

  2. Isolation of time: Each microservice should operate independently of other microservices and should not have dependencies on the timing of other microservices. This helps to ensure that the operation of one microservice is not affected by the timing of other microservices.

  3. Isolation of space: Each microservice should operate independently of other microservices and should not have dependencies on the location of other microservices. This helps to ensure that the operation of one microservice is not affected by the location of other microservices.

  4. Isolation of failure: Each microservice should be designed to fail independently, without affecting the operation of other microservices. This helps to ensure that a failure in one microservice does not cause a cascading failure in other microservices.


By adhering to these principles of isolation, organizations can ensure that their microservices architecture is scalable, resilient, and flexible and that each microservice can be deployed and managed independently.


Now that we are fully equipped with the knowledge of creating and developing microservices stay tuned for the second part of this blog which will focus more on some other topics related to reactive architecture such as sharding, Event Sourcing, CQRS, CRDTs and many more.


If you need help with your Software engineering requirements, Please contact 'Hello@fusionpact.com'


Know more about us by visiting https://www.fusionpact.com/

























bottom of page