Microservices are independently deployable services designed with a business domain in mind.
A service encapsulates functionality and connects it to other services over networks. One microservice represents an inventory, another order management, and yet another shipping, but together they constitute an entire e-commerce system.
Monolithic applications perform poorly as processing demands increase or reach a certain threshold. Microservices, which are primarily focused on distributed services while having an isolated service, are replacing monolithic architecture systems.
Applying microservices requires the effort to set up and scale each microservice to the Cloud. Microservices are gaining popularity steadily. Big players such as Amazon, Netflix, and Spotify as well as small enterprises are developing Microservice architecture-based systems.
Some disadvantage of monolithic architecture that leads to the need for adopting microservices are:
There is tight coupling (high interdependency) between individual components.
It is harder to be agile in the development process. Scaling monolithic applications requires cloning them to multiple servers, virtual machines, or containers.
Principles for Designing Microservices:
Principles are rules made in order to align what you are doing to some larger goal, similarly, some principles are defined for designing a higher-order application with independent decentralized microservices that should be considered while designing a microservices :
1. SRP: Single Responsibility Principle:
One Microservice -> One Responsibility.
Microservices that follow the single responsibility concept are easy to update and maintain than those that follow the multiple responsibility principle.
2. Build Around Business Capabilities:
You can organize your code to more accurately reflect the real-world environment that the software runs in by using techniques like domain-driven design. We apply the same concept to establish our service boundaries in microservice architectures. We can make it simpler to roll out new functionality and to recombine microservices in novel ways to provide new functionality to our consumers by structuring services around business domains.
3. Fault Tolerance:
Failure of one service will not impact the other services. Systems should detect problems rapidly and, if possible, automatically restore and restart service because they can happen at any time.
4. Failure Isolation
The more one microservice depends on another microservice being available, the more the health of one impacts the ability of the other to do its job.
There is another benefit to increasing isolation between services. When services are isolated from each other, much less coordination is needed between services. The less coordination needed between teams, the more autonomy those teams have, as they are able to operate and evolve their services more freely.
5. Loose Coupling:
Two significant things happen if we successfully create a loosely connected, well-encapsulated architecture and organizational structure. First, we can improve delivery performance by speeding up and stabilizing things while lessening burnout and the discomfort of deployment. Second, we can significantly expand our engineering team’s size while linearly raising productivity.
6. Automation:
As you add more microservices, you’ll have more moving parts to deal with — more processes, more things to configure, and more instances to monitor. And if you are managing your operational processes in a mostly manual way, this means that more services will require more and more people to do things.
So we need to focus on automation. Select tooling and technology that allows for things to be done in an automatic fashion.
7. Continous Monitoring:
We can monitor a typical monolithic program with a comparatively straightforward strategy. There are only a few machines for us to be concerned about. Because microservices-based apps are distributed, finding faults through a manual method is a difficult challenge. You require an automated monitoring system for precisely this reason. The issue with monitoring microservices is that they are frequently developed using various technologies and frameworks because they are intended to be independent of one another. As a result, it is challenging to decide how to monitor the system as a whole.
8. Command Query Responsibility Segregation (CQRS)
The Command Query Responsibility Segregation (CQRS) pattern refers to an alternate model for storing and querying information.
Instead of using a single model, as is typical, for both manipulating and retrieving data, we use different models to handle reads and writes. We could scale reads and writes independently thanks to the separate read and write models that were implemented in code and distributed as separate units.
Microservices Design Patterns:
1. Strangler Fig Pattern
Inspired by a type of plant, the pattern describes the process of wrapping an old system with the new system over time, allowing the new system to take over more and more features of the old system incrementally.
You intercept calls to the existing system — in our case the existing monolithic application. If the call to that piece of functionality is implemented in our new microservice architecture, it is redirected to the microservice. If the functionality is still provided by the monolith, the call is allowed to continue to the monolith itself.
2. Backend for Frontend (BFF)
BFF is a single purpose in nature — it is developed for a specific user interface. The BFF is tightly coupled to a specific user experience and will typically be maintained by the same team as the user interface, thereby making it easier to define and adapt the API as the UI requires, while also simplifying the process of lining up the release of both the client and server components.
3. Communication Through Common Data
This pattern is used when one microservice puts data into a defined location, and another microservice (or potentially multiple microservices) then make use of the data.
One microservice writes out a file that other microservices make use of
To implement this pattern, you need some sort of persistent store for the data. This pattern can be implemented very simply, using commonly understood technology. If you can read or write to a file or read and write to a database, you can use this pattern.
4. One Repository per Microservice (aka Multirepo)
With the one repository per microservice pattern, the code for each microservice is stored in its own source code repository.This approach leads to a straightforward mapping between source code changes and CI builds.
The source code for each microservice is stored in a separate source code repository
However, this pattern’s simplicity does present certain difficulties.
Particularly if they are trying to make changes across numerous sources simultaneously, developers may find themselves working with multiple repositories at once, which is frustrating.
5. Request-Response Communication
With request-response, a microservice asks a downstream service to perform a task and anticipates receiving a response containing the requested action.
This contact can either be carried out using a synchronous blocking call or an asynchronous non-blocking approach.