The architecture of a software system is the shape given to that system by those who build it. The form of that shape is in the division of that system into components, the arrangement of those components, and the ways in which those components communicate with each other.
The purpose of that shape is to facilitate the development, deployment, operation, and maintenance of the software system contained within it.
Good architecture makes the system easy to understand, easy to develop, easy to maintain, and easy to deploy. The ultimate goal is to minimize the lifetime cost of the system and to maximize programmer productivity.
A good architecture must support:
- The use cases and operation of the system: architecture must support required throughput and response time for each use case that demands it.
- The maintenance of the system: makes the system easy to change.
- The development of the system: partitioning the system into well-isolated, independently developable components that can be allocated to teams that can work independently of each other.
- The deployment of the system: A good architecture does not rely on dozens of little configuration scripts and property file tweaks. It does not require manual creation of directories or files that must be arranged just so. A good architecture helps the system to be immediately deployable after build.
Model-view-controller pattern
The model-view-controller (MVC) pattern divides an application into three components: A model, a view, and a controller.
The model, which is the central component of the pattern, contains the application data and core functionality. It is the dynamic data structure of the software application, and it controls the data and logic of the application. However, it does not contain the logic that describes how the data is presented to a user.
The view displays application data and interacts with the user. It can access data in the model but cannot understand the data, nor does it understand how the data can be manipulated.
The controller handles the input from the user and mediates between the model and the view. It listens to external inputs from the view or from a user and creates appropriate outputs. The controller interacts with the model by calling a method on it to generate appropriate responses.
Microservices pattern
Microservice is the process of implementing Service-oriented Architecture (SOA) by dividing the entire application as a collection of interconnected services, where each service will serve only one business need.
The microservices pattern involves creating multiple applications—or microservices—that can work interdependently, each service is self-contained and implements a single business capability. Although each microservice can be developed and deployed independently, its functionality is interwoven with other microservices.
Microservice Rules :
- Independent: Each microservice should be independently deployable.
- Coupling: All microservices should be loosely coupled with one another such that changes in one will not affect the other.
- Business Goal: Each service unit of the entire application should be the smallest and capable of delivering one specific business goal.
The principles used to design Microservices are as follows:
- Independent & Autonomous Services
- Scalability
- Decentralization
- Resilient Services
- Real-Time Load Balancing
- Availability
- Continuous delivery through DevOps Integration
- Seamless API Integration and Continuous Monitoring
- Isolation from Failures
- Auto -Provisioning
- Decomposition Design Patterns: provides insight on how to decomposed application in smaller microservices.
- Integration Design Patterns: handles the application behavior, how to get result of multiple services result in single call etc.
- Database Design Patterns: how to define database, should have a separate database per service or use a shared database.
- Observability Design Patterns: considers tracking of logging, performance metrices and so.
- Cross Cutting Concern Design Patterns: deals with service discovery, external configurations, deployment scenarios etc.
Decomposition Design Patterns:
- Business Capability: split by business activity targeted to generate value. For example, in an e-commerce platform, we can split system by Sales and Customer service. Business capabilities may overlap, resulting in redundant services, like develop payment on Sales and on Customer Service!
- Domain-Driven Design(DDD): DDD refers to business as a domain, For example, in an e-commerce platform, we can split system by Ordering, Shipping, Payment.
Design Patterns of Microservices
- Aggregator
- API Gateway
- Chained or Chain of Responsibility
- Asynchronous Messaging
- Database or Shared Data
- Event Sourcing
- Branch
- Command Query Responsibility Segregator
- Circuit Breaker
- Decomposition
1) Aggregator Pattern
a simple web module will call different services as per requirements, the "Aggregator" is responsible for calling different services one by one. If we need to apply any business logic over the results of the service A, B and C, then we can implement the business logic in the aggregator itself.
1.1) Proxy Pattern (sort of aggregator)
Build one level of extra security by providing a dump proxy layer. This layer acts similar to the interface.
1.2) Chained Pattern
Produces a single output which is a combination of multiple chained outputs, All the services will be chained up in a such a manner that the output of one service will be the input of the next service.
All these services use synchronous method. Also, until the request passes through all the services and the respective responses are generated, the client doesn’t get any output. So, it is always recommended to not to make a long chain, as the client will wait until the chain is completed
1.3) Branch Microservice Pattern
Allows the developer to configure service calls dynamically. All service calls will happen in a concurrent manner, which means service A can call Service B and C simultaneously, client can directly communicate with the service.
1.4) Shared Resource Pattern
the client or the load balancer will directly communicate with each service whenever necessary. This is the most effective designing pattern followed widely in most organizations.
2) API Gateway Design Pattern
- Acts as the entry point for all the microservices and can convert the protocol request from one type to other.
- Can also offload the authentication/authorization responsibility of the microservice.
- Can also be considered as the proxy service to route a request to the concerned microservice.
- Can send the request to multiple services and similarly aggregate the results back to the composite or the consumer service.
3) Asynchronous Message-Based Communication Design Pattern
If you have multiple microservices are required to interact each other and if you want to interact them without any dependency or make loosely coupled, than we should use Asynchronous message-based communication in Microservices Architecture. Because Asynchronous message-based communication is providing works with events. So events can place the communication between microservices, which called "event-driven communication".
Example use case can be like a price change in a product microservice. Price Changed event can subscribed from Shopping Cart microservice in order to update basket price asynchronously.
So if we summarize the async communication, The client microservice sending a message or event to the message broker systems and no need to wait reply. Because it aware of this is message-based communication, and it won’t be respond immediately. A message or event can includes some data. And these messages are sent through asynchronous protocols like AMQP over the message broker systems like Kafka and Rabbitmq.
There are two kinds of asynchronous messaging communication:
- Single receiver message-based communication that we can say One-to-One model.
- Multiple receivers message-based communication that we also said Publish/Subscribe model.
4) Database or Shared Data Pattern
use shared database to solve the follows problems:
- Duplication of data and inconsistency
- Different services have different kinds of storage requirements
- Few business transactions can query the data, with multiple services
- De-normalization of data
Advantages of sharing the database:
- the simplest way of integration
- no middleman involved
- no latency overhead
- quick development time
5) Event Sourcing Design Pattern
Instead of storing just the current state of the data, use an append-only store to record the full series of actions taken on that data.
These events are stored as a sequence of events to help the developers track which change was made when. So, with the help of this, you can always adjust the application state to cope up with the past changes. You can also query these events, for any data change and simultaneously publish these events from the event store. Once the events are published, you can see the changes of the application state on the presentation layer.
We can use MixPanel for this!
============================================
𝗟𝗼𝗮𝗱 𝗕𝗮𝗹𝗮𝗻𝗰𝗲𝗿 𝘃𝘀. 𝗥𝗲𝘃𝗲𝗿𝘀𝗲 𝗣𝗿𝗼𝘅𝘆 𝘃𝘀. 𝗔𝗣𝗜 𝗚𝗮𝘁𝗲𝘄𝗮𝘆
What are the differences between a load balancer, a reverse proxy, and an API gateway?
All three are used to optimize and manage web traffic. However, they vary in their function and use cases:
A 𝗹𝗼𝗮𝗱 𝗯𝗮𝗹𝗮𝗻𝗰𝗲𝗿 is a device that distributes incoming network traffic across multiple servers. The goal is to ensure that no single server is overwhelmed with traffic, which can lead to slow response times or even downtime. Load balancers are ideal for high-traffic websites or applications that need to handle a large volume of requests.
A 𝗿𝗲𝘃𝗲𝗿𝘀𝗲 𝗽𝗿𝗼𝘅𝘆, on the other hand, is a server that sits between the client and the webserver. The reverse proxy intercepts requests from clients and forwards them to the appropriate server. The reverse proxy can also cache frequently requested content, which can help improve performance and reduce server load. Reverse proxies are ideal for websites or applications that need to handle a large number of concurrent connections.
An 𝗔𝗣𝗜 𝗴𝗮𝘁𝗲𝘄𝗮𝘆 is a server that acts as an intermediary between clients and backend servers. The API gateway is responsible for managing API requests, enforcing security policies, and handling authentication and authorization. API gateways are ideal for microservices architectures, where multiple services need to be accessed through a single API.
====================================
𝐖𝐡𝐚𝐭 𝐚𝐫𝐞 𝐀𝐫𝐜𝐡𝐢𝐭𝐞𝐜𝐭𝐮𝐫𝐚𝐥 𝐏𝐚𝐭𝐭𝐞𝐫𝐧𝐬?
Architectural patterns are standard strategies that define structural organization for software systems, providing a template for the architecture's design and module interactions.
Here are famous architectural patterns:
➡ 𝐄𝐯𝐞𝐧𝐭-𝐃𝐫𝐢𝐯𝐞𝐧: An event-driven architecture is a framework that orchestrates behavior around the production, detection, and consumption of events. Example use case: A real-time analytics system where events are generated by user activities and processed immediately.
➡ 𝐋𝐚𝐲𝐞𝐫𝐞𝐝: A layered architecture is a hierarchical pattern for structuring a system into groups of related functionalities, each layer having a specific role. Example use case: A web application with a presentation layer, business logic layer, and data access layer.
➡ 𝐌𝐨𝐧𝐨𝐥𝐢𝐭𝐡: A monolithic architecture is a traditional unified model for the design of a software program where all components are interwoven and interdependent. Example use case: A small-scale e-commerce website where the user interface, server-side application, and database are all on a single platform.
➡ 𝐌𝐢𝐜𝐫𝐨𝐬𝐞𝐫𝐯𝐢𝐜𝐞: Microservices architecture is an approach where a single application is composed of many loosely coupled and independently deployable smaller services. Example use case: A large-scale cloud-based application like Netflix, where each service runs a unique process and communicates through a well-defined, lightweight mechanism to serve a business goal.
➡ 𝐌𝐕𝐂 (𝐌𝐨𝐝𝐞𝐥-𝐕𝐢𝐞𝐰-𝐂𝐨𝐧𝐭𝐫𝐨𝐥𝐥𝐞𝐫): MVC is a design pattern that separates an application into three interconnected components: the model, the view, and the controller. Example use case: A desktop GUI application where user interface data (view), data manipulation (model), and input control (controller) are separated to simplify maintenance and scalability.
➡ 𝐌𝐚𝐬𝐭𝐞𝐫-𝐒𝐥𝐚𝐯𝐞: The master-slave pattern is a model where one master component controls one or more subordinate instances, called slaves. Example use case: A database replication system where the master database manages writes and the slave databases handle read operations to distribute the load.