[Microservice Architecture Evolution] An article to understand the patterns and best practices from monolithic to microservice architecture

In this article, we'll learn how to design a microservices architecture using design patterns, principles, and best practices. We will use the correct architectural design patterns and techniques.


By the end of this article, you will understand how to design a system on a microservices distributed architecture for high availability, high scalability, low latency, and resilience to network failures to handle millions of requests.

67256c4db45be4ed2db2416396fa1983.png

Event-Driven Architecture

This course will be a journey of software architecture design, gradually evolving from architectural monolithic to event-driven microservices.
We'll start with the basics of software architecture by designing an overall architecture for e-commerce that handles a small number of requests.

6be3d6975c796f686c010378cb9daa2a.png

Journey of Design Architectures

Then gradually evolve the architecture

  • layered architecture

  • SOA

  • microservice

  • Finally, the event-driven microservice architecture

Designed together to handle millions of requests.

Step-by-step design architecture with lessons


In this course, we'll learn how to design microservice architectures using design patterns, principles, and best practices. We'll start by designing monoliths to event-driven microservices, and use the right architectural design patterns and techniques together.

article


There will be both theoretical and practical information in the article stream;

  • We'll learn about a particular pattern, why and where we should use it

  • Afterwards, we'll see a reference architecture for applying these patterns

  • Afterwards, we will apply this newly learned pattern to design our architecture

  • In the end, we will decide which technologies are available as options for this architecture.

So we will iterate and evolve the monolithic architecture to an event-driven microservice architecture.

architecture evolution


We will evolve these schemas according to the problem

  • How can we scale the application?

  • How many requests does our application need to handle?

  • How many seconds of latency is acceptable for our arch?

Therefore, we evolve these questions according to the following questions;

e076b1045268d6a2f2df6d66b5371e81.png

Scalability and reliability are measures of how well your application serves end users. If our e-commerce application can serve millions of users without noticeable downtime, then we can say that the system is highly scalable and reliable. Scalability and availability can be major factors in designing a good architecture.

  • Scalability = eCommerce application should be able to serve millions of users

  • Availability = eCommerce applications should be available 24/7

  • Maintainability = eCommerce application should be developed for several years

  • Efficiency = eCommerce applications should respond with acceptable latency,

  • eg < 2 seconds - short response delay


Requests per second and acceptable latency


Ok, let's talk about acceptable latency,
how can we make our application have acceptable latency if our application is used by more and more users?
Please see the form;

3fbdda907d925eade170ab608d041f9b.png

As you can see in the table, we're going to start a small e-commerce application that only gets 2K concurrent users and gets 500 requests per second.
We will design our e-commerce architecture based on these expected volumes.
After that, as our business grows, it will require more resources to accommodate larger request volumes, and we'll see how we evolve our architecture based on those numbers.


monolithic architecture


Over decades of software development, there are many approaches and patterns that have evolved, all with their own benefits and challenges.
So we'll start by understanding the existing ways of building our e-commerce application, then evolve and migrate to the cloud.
In order to understand cloud-native microservices, we need to understand what a monolithic application is and how we move from monolithic to microservices.

9a8d787899c2325a0d55060291ac73db.png

For legacy applications, we can say that most legacy applications are primarily implemented as a monolithic architecture.
If all the functionality of a project exists in one codebase,
then the application is known as a monolithic application. In the monolithic pattern, everything such as the user interface, business code, and database calls are contained in the same code base.
All application concerns are contained in one large deployment.
Even a monolithic application can be designed in different layers such as presentation layer, business layer, and data layer, and then deploy that code base as a single jar/war file.
The holistic approach has several advantages, and we'll discuss them in the upcoming videos. But let me say some major pros and cons here.
Since it's a single codebase, it's easy to pull and start projects.
Due to project structure in 1 project and easy to debug business interactions across different modules.
Unfortunately, monolithic architecture has many disadvantages, we can say that;

  • Over time, its code size becomes too large, which is why it's really hard to manage.

  • Difficult to work in parallel on the same codebase.

  • Difficulty implementing new features on legacy large monolithic applications

  • Any changes require deploying a new version of the entire application.

Etc..
As you can see, we understand monolithic architecture.


When to Use a Monolith


Even monolithic architecture has many disadvantages, if you are building small application then monolithic architecture is still one of the best architecture you can apply to your project. Because, in many ways, monolithic applications are simple.
They are simple:

  • put up

  • test

  • deploy

  • Troubleshooting

  • Vertical zoom (zoom in)

  • Very easy and fast.

It is simple to develop compared to microservices, which require skilled developers to identify and develop services. Easier to deploy since only one jar/war file is deployed.

Design a monolithic architecture


In this section, we will step through the design of an e-commerce application with a monolithic architecture.
We will iterate the architectural design one by one according to the requirements.
We should always start by writing down FR (Functional Requirements) and NFR (Non-Functional Requirements).


functional requirements

  • list products

  • Filter products by brand and category

  • Add product to cart

  • Apply for a discount coupon and view the total cost of all items in your cart

  • Check out the cart and create an order

  • List my old orders and order item history


non-functional requirements

  • scalability

  • Increase concurrent users

Also, it's good to add principles to our pictures to always remember them.


in principle

  • KISS

  • YAGNI


We will consider these principles when designing the architecture.

05bce148cffcd5ad4eb1ca73708313b5.png

As you can see, we designed our e-commerce application using a monolithic architecture.
We added the big e-commerce box, what are the components of our e-commerce application; store UI, catalog service, SC service, discount service, order service. As you can see, all the modules of this traditional web application are a single artifact in the container.
This monolithic application has a huge codebase with all modules. If a new module is introduced to the application, changes must be made to the existing code and then the artifact with the different code deployed to the Tomcat server. We follow our KISS principle of keeping it simple.
We'll refactor our design as needed and iterate together incrementally.


Scalability of monolithic architecture


As you can see, we scaled the monolithic architecture by horizontal scaling by adding 2 application servers and placing a load balancer in front of the monolithic application between the client and the e-commerce application.
In order to provide scalability on a monolithic architecture. We need to create an e-commerce application server. And put the load balancer in front of our application.
Basically, the load balancer will use a consistent hashing algorithm to accommodate and send requests to our eCommerce application servers. This will provide an equal load to the server.


Adapt technology stack


We'll discuss technology choices - adapting the technology stack.

d6dc6b44419740fcb32af107369c9275.png

As you can see in the image, we have selected potential options for our e-commerce monolithic application. NGINX is a very good choice for load balancing and Java - Oracle is the standard implementation for such applications.


microservice architecture


Microservices are small business services that work together and can be deployed autonomously/independently.


From Martin Fowlers microservices article;


The microservices architectural style is an approach to developing a single application as a set of small services, each running in its own process and communicating with a lightweight mechanism (usually HTTP or gRPC API).


So we can say that microservices architecture is a cloud-native architectural approach where an application is composed of many smaller components that are loosely coupled and independently deployable.


microservice

  • — own technology stack, including database and data management model;

  • — Communicate with each other through a combination of REST APIs, event streams, and message brokers;

  • — Organized by business capabilities, the lines separating services are often referred to as bounded contexts.

In the next sections, we will also see how to decouple microservices from bounded contexts.


microservice characteristics


Microservices are small, independent and loosely coupled. A small development team can write and maintain the service. Each service is a separate code base that can be managed by a small development team.
Services can be deployed independently. Teams can update existing services without having to rebuild and redeploy the entire application.
Services are responsible for saving their own data or external state. This differs from the traditional model, where a separate data layer handles data persistence.


Benefits of Microservices Architecture


agile.

  • One of the most important characteristics of microservices is that services are smaller and independently deployable.

  • Small but dedicated team.

  • A microservice should be small enough that a single functional team can build, test and deploy it.


scalability.

  • Microservices scale independently, so you can scale subservices that require fewer resources without scaling the entire application.


Challenges of Microservices Architecture


complex.


A microservice application has many services that need to work together and should create value. Since there are many services, this means more moving parts than a monolithic application.


Network issues and delays.


So since microservices are small and communicate with inter-service communication, we should manage network issues.


Data Integrity.


Microservices have their own data persistence. Therefore, data consistency can be a challenge.

Design microservice architecture


In this section, we will design a microservices architecture step by step. Iterate the arch design one by one according to the requirements.

da001d93b5dd4b7bcc4a39d98bd1ae95.png

We followed the database-per-service pattern when designing the microservice architecture and the database where all microservices are placed. Microservices are decomposed from monolithic application modules with independent services.
So now these databases can be multilingual persistent. That is to say, Product ms can use NoSQL document database, SC ms can use NoSQL key-value pair database, and Order ms can use Relational database according to ms data storage requirements.


development framework


Let's look at the microservice architecture diagram and think about what is missing in this architecture? What are the pain points of this architecture? How can we evolve this architecture into a better architecture that improves scalability, availability, and can accommodate more concurrent requests?

9d204862efa87afee9a4dad5a2d8e54c.png

Seeing that the UI and Microservices communication is straightforward, and it seems difficult to manage the communication.
We should focus on microservice communication now!


Microservice Communication


One of the biggest challenges when migrating to a microservices-based application is changing the communication mechanism. Because microservices are distributed, microservices communicate through inter-service communication at the network level. Each microservice has its own instance and process.
Therefore, services must interact using an inter-service communication protocol such as HTTP, gRPC, or the message broker AMQP protocol.
Since microservices are complex structures of independently developed and deployed services, we should be careful when considering communication types and managing them into the design phase.


Microservice Communication Design Pattern - API Gateway Pattern


The API Gateway pattern is recommended if you want to design and build complex microservices-based applications with multiple client applications.
This pattern provides a reverse proxy to redirect or route requests to your internal microservice endpoints. API Gateway provides a single endpoint for client applications and internally maps requests to internal microservices. We should use API Gateway between client and internal microservices.
API Gateway can handle cross-cutting issues like authorization
, so instead of writing each microservice, authorization can be handled in a centralized API Gateway and sent to internal microservices. The api gateway also manages routing to internal microservices and is able to aggregate multiple microservice requests in 1 response.
In summary, an API Gateway sits between client applications and internal microservices. It acts as a reverse proxy and routes requests from clients to backend services. It also provides cross-cutting concerns such as authentication, SSL termination, and caching.


Designing an API Gateway — Microservice Communication Design Patterns


We'll iterate on our e-commerce architecture by adding the API Gateway pattern.

7b6c054e3dc73ada2596299c1f4f7140.png

You can see an image where client requests are collected at a single entry point and routed to internal microservices.
This handles client requests and routes internal microservices,
and also aggregates multiple internal microservices into a single client request
and enforces cross-cutting concerns such as authentication and authorization, rate limiting and throttling, etc.


development framework


We will continue to evolve our architecture, but take a look at the current design and think how can it be improved?
Here are several client applications connecting to a single API Gateway.
We should be careful about this situation, because if we put a separate api gateway here, it means there may be a single point of failure risk here.
This would be an anti-pattern if these client applications grow, or add more logic to the business complexity in the API Gateway.
So we should use the BFF-backends-for-frontends pattern to solve this problem.


Backends for Frontends Pattern BFF — Microservice Communication Design Pattern


The backend of the frontend pattern basically separates the api gateway according to the specific frontend application. So we have several backend services that are consumed by the frontend application, and between them we put API Gateway to handle routing and aggregation operations.

But this would lead to a single point of failure, so to solve this problem, BFF provides to create multiple API gateways and group client applications according to their boundaries and split them into different API gateways.

4c0e1bb20ac2d6c8f03c712ac0fcd0bc.png

A single complex api gateway can be risky and become a bottleneck in your architecture. Larger systems often expose multiple API Gateways by grouping client types such as mobile, web, and desktop capabilities. BFF mode is useful when you want to avoid customizing a single backend for multiple interfaces.
So we should create several api gateways based on the UI.
These api gateways provide the best match to the needs of the front-end environment without worrying about impacting other front-end applications.
The Backend for Frontends pattern provides directions for implementing multiple gateways.


Designing Backends for Frontend Patterns BFF — Microservice Communication Design Patterns


We will iterate on our eCommerce architecture by adding more API Gateway patterns based on the Backend pattern BFF.

30f5172c236df77ba18cb43d6ded6a72.png

As you can see, we have added several API Gateways to our application. These api gateways provide the best match to the needs of the front-end environment without worrying about impacting other front-end applications. The Backend for Frontends pattern provides directions for implementing multiple gateways.


Service-to-service communication between internal microservices in the backend - microservice communication design pattern


Ok, we have created API Gws in our microservice architecture. And says that all these synchronous requests come from client side and go to internal microservices via api gws.
But what if a client request needs to access multiple internal microservices? How do we manage inter-microservice communication?

f1db1bad55ebb1b605e33de7bfd0e640.png

When designing a microservice application, we should pay attention to how the internal microservices communicate with each other in the backend. Best practice is to minimize inter-service communication as much as possible.
However, in some cases we cannot mitigate these internal communications due to customer requirements or requested actions requiring access to multiple internal services.
For example, look at the image and consider the use case:

  • User wants to checkout the cart and create an order

So how do we implement this request?
So these internal calls make each microservice coupled, in our case sc - Product and Pricing microservices are interdependent and coupled.
If one of the microservices fails, it cannot return data to the client, so it does not have any fault tolerance. If the dependencies and coupling of microservices increase, it will create many problems and weaken the power of microservices architecture.
This starts a set of actions if the client checks out the cart.
So if we try to execute this order use case using request/response synchronous message pattern then it will look like this image.
As you can see, there are 6 simultaneous http requests for one client http request.
So it's clear that adding latency and negatively impacting the performance, scalability, and availability of our system.
If we have this use case, what if step 5 or 6 fails, or what if some intermediate service goes down?
Even if there is no downtime, some services may be too busy to respond in a timely manner, resulting in unacceptably high latencies.
So what is the solution to this need?
We can apply 2 approaches to solve this problem,
1- Change the microservice communication to an asynchronous way with the message broker system, we will see this in the next section.
2- Aggregate some query operations in 1 api gw using service aggregator pattern.


Service Aggregator Pattern - Microservice Communication Design Pattern


To minimize service-to-service communication, we can apply the Service Aggregator pattern. Basically, the service aggregator design pattern is to receive requests from clients or api gw, then dispatch requests to multiple internal backend microservices, then combine the results and respond to the originating request in 1 response structure.

ec147ebdae44e841cead002e47098cc9.png

Implemented with the service aggregator pattern, we can reduce chat and communication overhead between clients and microservices


Design——Service Aggregator Pattern——Service Registration Pattern——Microservice Communication Design Pattern


In this section, we will iterate on our e-commerce architecture by adding Service Aggregator Pattern - Service Registry Pattern - Microservice Communication Design Pattern.

14d0af8f97d3271214e68c8b4e23ae84.png

As you can see, we have applied the service aggregator pattern - service registry pattern for our e-commerce architecture.


Message-based asynchronous communication of microservices


Synchronous communication is good if your communication is only between a few microservices. But when it comes to several microservices that need to call each other and wait for some long operation until completed, we should use asynchronous communication.

a0f8ae08bc9bb18ca06813c0c6459d93.png

Otherwise, the dependencies and coupling of microservices will create bottlenecks and cause serious problems for the architecture.
If you have multiple microservices that need to interact with each other
If you want to interact with them without any dependencies or loose coupling, then we should use asynchronous message based communication in microservice architecture.
Because asynchronous message based communication provides event handling. So events can place communication between microservices.
We call this communication event-driven communication.


Publish-Subscribe Design Pattern


Publish-subscribe is a message delivery model, the sender of the message is called the publisher, and the specific receiver is called the subscriber.

d30632d4ee4055161f7f39cbdaf0ffed.png

So the publisher does not send the message directly to the subscriber.
Instead, the published messages are categorized and sent to the message broker system without knowing which subscribers are there.
Similarly, subscribers express interest and only receive messages of interest, without knowing which publishers sent them.


Design - Publish/Subscribe Message Broker - Microservice Asynchronous Communication Design Pattern


In this section, we iterate on our e-commerce architecture by adding a Pub/Sub message broker to provide a microservice asynchronous communication design.

c5a7be40d617b29f01073d1eb38cd12c.png

As you can see, we have applied Pub/Sub Message Broker — Microservice Asynchronous Communication Design Pattern.
If we tune the technology stack, we basically start with the option of a Pub/Sub message broker. You can choose 2 good options;


1- Kafka
2- RabbitMQ


Microservice Data Management


In a monolithic architecture, it's great to query different entities, since a single database keeps data management simple. Querying data across multiple tables is simple. Any changes to the data are either updated together or rolled back altogether. The strictly consistent relational database has ACID transaction guarantee, which is convenient for data management and query.
But in microservices architecture, when we use "polyglot persistence"
it means that each microservice has different databases including relational databases and no sql databases, we should set policies to manage these when performing user interaction data.
This means that we have several patterns and practices when dealing with data interactions between microservices, which we will learn in this section.
Microservices are independent and only perform specific functional requirements, for our case in eCommerce application we have Product, Basket, Discount, Order microservices need to interact with each other to perform customer use case. This means they often need to be integrated with each other. Most of these integrations query per-service data for aggregation or logic execution.


CQRS design pattern


CQRS is one of the important patterns for querying between microservices. We can use CQRS design pattern to avoid complex queries to get rid of inefficient joins. CQRS stands for Command and Query Responsibility Separation. Basically, this pattern separates the read and update operations of the database.
To isolate commands and queries, it's best practice to physically separate the read-write database from the 2 databases. In this way, if our application is read intensive, meaning more reads than writes, we can define custom data schemas to optimize queries.

d9e1766fc264895ef3a1a0f9e86afc35.png

The Materialized View pattern is a good example of implementing reads from a database.
Because in this way, we can avoid complex joins and mappings with predefined fine-grained data for query operations.
With this isolation, we can even use different databases for reading and writing database types, such as a no-sql document database for reading and a relational database for crud operations.


Event Sourcing Pattern


We have learned the CQRS pattern, and the CQRS pattern is mainly used with the Event Sourcing pattern. When using CQRS with Event Sourcing pattern, the main idea is to store events into write database, which will be the source of real event database.
Afterwards, the read database of the CQRS design pattern provides a materialized view of the data with denormalized tables. Of course, this materialized view reads from the database consuming events from writes to the database and transforms them into a denormalized view.

fffd91aeff9bc2f09d35c7410d919890.png

With the application of the Event Sourcing pattern, it is changing to the operation of saving data into the database. Instead of saving the latest state of the data into the database, the Event Sourcing pattern provides saving the data events in order of all events into the database. This event database is called the event store.
It does not update the state of the data record, but appends each change to a sequential list of events. Thus, the event store becomes the source of truth for the data. These event stores are then transformed into read databases following the materialized view pattern. This conversion operation can be handled by a publish/subscribe pattern with a message broker system's publishing events.


Design Architecture - CQRS, Event Sourcing, Eventual Consistency, Materialized View


We will design our e-commerce architecture by applying CQRS, Event Sourcing, Eventual Consistency, Materialized View.

1801515693a8fbac7d4fa5ef9933dcc6.png

So when a user creates or updates an order, I'll write to the database using a relation, and when a user queries an order or order history, I'll read the database using no-sql and make them when syncing the 2 databases using a message broker system Keep consistent application publish/subscribe patterns.
Now we can think about the tech stack for these databases, I will use SQL Server for relational writes to the database and Cassandra for SQL-less reads. Of course, we will use Kafka to synchronize these 2 databases with the pub/sub Kafka topic exchange.
As you can see, we have completed the design of the microservice database schema. Let's take a deep dive into these event-driven architectures in microservices.


Event-driven microservice architecture


Basically event-driven microservice architecture refers to communicating with microservices through event messages. We saw this in the publish/subscribe pattern in the microservices asynchronous communication section and the Kafka message broker system.
We said that with event-driven architecture we can have asynchronous behavior and loosely coupled structures. For example, instead of sending requests when data is needed, services consume them through events. This will provide a performance boost.

4937f36d1d966c862d51a979f7fcbd2f.png

But there are also huge innovations in event-driven microservice architectures, such as using real-time messaging platforms, stream processing, event hubs, real-time processing, batch processing, data intelligence, etc.
So we can make this event-driven approach more general and have real-time event processing capabilities as this architecture evolves.
According to this new event-driven microservice architecture, everything is communicated through Event-Hubs. We can think of Event-Hubs as a large event storage database that can be processed in real time.


Design Architecture - Event-Driven Microservice Architecture


We will design our e-commerce application using an event-driven microservices architecture.

949ac9d5f921c34cad4b5571deb1f014.png

Now let's decide to use the technology stack in this architecture. Of course, we should choose Apache Kafka - as event hub and Apache Spark, for real-time and near-real-time streaming applications that transform or react to streams of data.
As you can see, now we have a reactive design for event-driven microservice architecture.
Now we can ask the same question;


How many concurrent requests can accommodate our design?

79e7909c54170178b950d0ae25b975c9.png

With this state-of-the-art event-driven microservices architecture, it is deployed using containers and an orchestrator to satisfy targeted concurrent requests with low latency.
Because the architecture is completely loosely coupled and designed for high scalability and high availability.
As you can see, we designed the e-commerce microservices architecture with aspects of the design principles and patterns. You are now ready to design your own architecture with these learnings and know how to use these pattern toolboxes in your designs.

This article: https://architect.pub/monolithic-microservices-architecture-patterns-best-practices
Discussion: Knowledge Planet [Chief Architect Circle] or add WeChat trumpet [ca_cto] or add QQ group [792862318]
No public
 
【jiagoushipro】
【Super Architect】
Brilliant graphic and detailed explanation of architecture methodology, architecture practice, technical principles, and technical trends.
We are waiting for you, please scan and pay attention.
WeChat trumpet
 
[ca_cea]
50,000-person community, discussing: enterprise architecture, cloud computing, big data, data science, Internet of Things, artificial intelligence, security, full-stack development, DevOps, digitalization.
 

QQ group
 
[285069459] In-depth exchange of enterprise architecture, business architecture, application architecture, data architecture, technical architecture, integration architecture, security architecture. And various emerging technologies such as big data, cloud computing, Internet of Things, artificial intelligence, etc.
Join the QQ group to share valuable reports and dry goods.

video number [Super Architect]
Quickly understand the basic concepts, models, methods, and experiences related to architecture in 1 minute.
1 minute a day, the structure is familiar.

knowledge planet [Chief Architect Circle] Ask big names, get in touch with them, or get private information sharing.  

Himalayas [Super Architect] Learn about the latest black technology information and architecture experience on the road or in the car. [Intelligent moments, Mr. Architecture will talk to you about black technology]
knowledge planet Meet more friends, workplace and technical chat. Knowledge Planet【Workplace and Technology】
LinkedIn Harry https://www.linkedin.com/in/architect-harry/
LinkedIn group LinkedIn Architecture Group https://www.linkedin.com/groups/14209750/
Weibo‍‍ 【Super Architect】 smart moment‍
Bilibili 【Super Architect】

Tik Tok 【cea_cio】Super Architect

quick worker 【cea_cio_cto】Super Architect

​​​​​​​

little red book [cea_csa_cto] Super Architect  

website CIO (Chief Information Officer) https://cio.ceo
website CIOs, CTOs and CDOs https://cioctocdo.com
website Architect practical sharing https://architect.pub   
website Programmer cloud development sharing https://pgmr.cloud
website Chief Architect Community https://jiagoushi.pro
website Application development and development platform https://apaas.dev
website Development Information Network https://xinxi.dev
website super architect https://jiagou.dev
website Enterprise technical training https://peixun.dev
website Programmer's Book https://pgmr.pub    
website developer chat https://blog.developer.chat
website CPO Collection https://cpo.work
website chief security officer https://cso.pub    ‍
website CIO cool https://cio.cool
website CDO information https://cdo.fyi
website CXO information https://cxo.pub

Thank you for your attention, forwarding, likes and watching.

Guess you like

Origin blog.csdn.net/jiagoushipro/article/details/131318735