Microservices: What They Are, How They Work and Good Implementation Practices

To start with, many will be familiar with the concept of microservice, others have simply heard of them, but what are they? Microservices are software components at their lowest possible level of functionality. They are components that can have isolated functionality and that achieve great decoupling. This is in contrast to traditional monolithic software that compiles all components in one piece.

Microservices are independent, in other words, they only need to be hosted in containers with minimum requirements for their execution and that they can interact with other microservices depending on the need for use.

Why or when to use microservices?

Microservices allow you to execute functions separately and, if for any reason one service fails, the rest will continue to work without being affected by the microservice that has problems.

In the case of monolithic applications, if we have a problem with a component, we must stop the execution, correct and deploy the new version with the fix made. It would mean that we have to stop the entire system, affecting other components that worked properly and that are not related to the component that failed!

© Kranio 2021
© Kranio 2021
Now that you know what microservices are, you'll wonder how they'll do it to make each one work and talk to each other.

Well, to implement microservices, there are reference models that we can follow. These models guide you to ensure that when you separate a set of functions into microservices, they are perfectly decoupled and there is no dependency between them.

Reference models

To implement a microservices architecture, you must consider the following aspects:

  • Perform a prior analysis and define why a microservices architecture is necessary.
  • Define which reference model is appropriate to solve the need (reference architectures).
  • An implementation model with which you can specify the implementation of the components of the reference model. For example, if you use Java and Spring, you must have all the components of this framework, necessary to support this architecture.
  • A deployment model that allows you to define how the components of the architecture are going to be deployed. For example, if you use containers, Docker and whatever is necessary to use the applications in these containers.

Given the above, to have a good microservices architecture model, you must at least consider the following necessary components and concepts:

  • Central configuration server (centralized source repository, versioning and software lifecycle).
  • Registration/discovery service (registration of microservices, provision of endpoints).
  • Load balancing (service orchestrator).
  • Fault tolerance (I work on solving faults in isolation without affecting the rest of the calls).
  • Service Exhibition (Gateway).
  • Authorization component (implementation of a security layer).
  • Monitoring (tools to monitor pod health, workload, failures).

Since you've considered these components, it's time to think about how we structure each microservice. To begin with, you must have a previous analysis related to the business domain to model microservices. Knowing and managing the company's domain, objectives and requirements is one of the great challenges, since there is no mechanical process that guides us to a perfect design. But what you can do is follow architectures that separate by layers and isolate the domain in a way that the other components communicate with each other, without being affected or mixed.

Hexagonal Architecture

The Hexagonal architecture is a software design pattern, which seeks to decouple the application by components. These components form a series of layers that will be easily connected to each other using ports and adapters. A port is the definition of a public interface and an adapter is a specialization of a port for a specific context. Thus, the components can become interchangeable at any level or layer. In addition, we can isolate automated tests without having to go through several layers to test a specific functionality.

This Architecture is represented by a Hexagonal shape, where the sides represent the ports, which allow us to go to an inner or outer layer of the application. Each component can be connected to another component through these ports. Communication between ports will always follow a specific protocol (for example an API) that will depend on the objective or function you have.

Hexagonal Architecture - © Kranio 2021

Hexagonal Architecture

Infrastructure Layer

This layer contains components that relate to the integration of other components of the microservice, for example, an external service component such as user authentication, or a messaging service (sending mail), which is not a core component of the domain.

Application Layer

This layer contains, for example, a component like Spring in Java and it contains the different use cases.

Domain Layer

This layer contains the entire business domain of the application, that is, entities, repositories, model, events, services.

DDD (Domain-Guided Design) Architecture

It is a software architecture design where business logic is the determining factor in the construction of the software. It allows you to map the business on software artifacts and organize them in such a way as to solve business problems.

The modeling is based on business use cases. There is a context, which is created out of the need to solve a problem. We have to set limits for solving this problem, limiting the requirements so that they are not redundant or do more than is necessary for the solution. With that, we were able to get an idea of the ideal size that the microservice should be. This point is important because not setting limits leads to having a microservice that is too large and generating unnecessary connections. Cohesion is a key concept in the delimitation of each component.

DDD levels or layers

The structure is composed of layers or levels that are well defined and structured in such a way that their components are not mixed between layers. For example, we ensure that business entities are not in layers that do not belong to the business domain, or that the logic of persistence is found in the infrastructure layer and not in the presentation layer.

Levels or layers interact with each other through their own interface, keeping their internal logic encapsulated.

Dependency on levels or layers - © Kranio 2021

The different layers are defined as follows:

Presentation Layer (UI): It is the layer that interacts with the different clients. This layer is the one that shows and receives data. It can be represented by a graphical interface of a website or some device.

Application Layer: Coordinates the actions to be performed on the domain. Delegate business actions to the domain layer. It is dependent on the Infrastructure and Domain layer.

Domain Layer: Contains business rules and logic, entities and persistence details. It is the core of the software. It has no dependencies with other layers in the model, but yes, other layers depend on it.

Infrastructure Layer: In this layer there are encapsulated implementations and functionalities that are not in the business domain, for example connections to databases, integrations with other external services, email notification service, etc. It has dependencies with the domain layer.

Cohesion and Coupling

Well-designed monolithic applications tend to have a high cohesion, since all their components are integrated in the same context, making it easy to understand the relationship of each component that is integrated. For microservices, it is a constant task to maintain cohesion, since they are an isolated and low-coupled component, there are cases in which there is so much separation between them that the cohesion of a service is lost and how it is related to other microservices that may exist in a given context.

Microservices must be designed around company functionalities, they must have flexible coupling and also a high functional cohesion. This means that microservices must exhibit low coupling, but also maintain high cohesion.

If a component (microservice) requires a change, and this change does not affect the other microservices that interact with it, that is, they should not be updated because of this change, it means that the microservice has a high cohesion. It is designed for a unique and well-defined purpose that allows domain knowledge to be encapsulated in such a way that it can be abstracted from the customers who consume it. If this design is not well defined and is decoupled more than necessary, cohesion between components may be lost.

Advantages

Agility: Since they are implemented independently, it is easier to manage them, in the event of a failure, a single service can be updated without having to redeploy the entire application.

Small, focused teams: Because the size of microservices is small, a small team is required to manage them. This speeds up productivity because with small teams, communication flows better. Unlike larger teams where communication tends to be slower, resulting in less agility.

Small codebase: Monolithic applications tend to grow over time and have new functionalities, which complicates code maintenance, as they have to modify several layers of the application. Microservice architectures minimize this dependency by allowing you to easily add new features.

Mixture of technologies: The microservice architecture allows flexibility in the language of each microservice, this improves the implementation of a service according to the most appropriate technology for a functionality. It also allows you to have experts in a specific technology and not have a team forced to use a technology that you are not used to using and that you must research.

Error isolation: microservices being independent, if an error occurs, the error does not prevent the operation of the other microservices, so it will not be necessary to stop the entire application to correct the errors.

Horizontal Scalability: There is no migration of the entire system to hardware with better performance, since, since they are independent services, the concept of service replication is used. This scalability allows you to add resources that are adaptable to the growth of the workload.

Challenges

Complexity in management: having an architecture distributed in several microservices, it becomes more complex to manage their integration. Therefore, it is necessary to have tools that allow us to have an overview of all of them in the face of possible failures.

High memory consumption: The microservice architecture works in a distributed manner and each microservice is independent, so resources must increase, unlike a monolithic architecture.

Developer profile: It requires developers with high experience in development and versioning, knowledge in network latency and load balancing.

Initial time investment: When implementing this architecture, it requires a greater investment of time since it requires greater analysis to properly separate the services and implement communication between them.

Personal Vision

When starting to design the architecture and its components, you should keep in mind that it is key to maintain cohesion to achieve a well-defined architecture. In addition, you must have a high level of management and understanding of the business, since the domain is the most important component and on which you should focus the most. If you don't have a strong understanding of the business, it will be more complex to implement architectures like these.

Another important point is having the right equipment to implement this architecture. You must have the necessary expertise to address the components and tools required to build an architecture like this, in addition to additional tools such as monitoring all its artifacts.

Do you want to implement a scalable and efficient microservices architecture?

At Kranio, we design microservice-based solutions that adapt to your business needs. We use principles such as DDD, events, containers, and CI/CD automation to help you scale sustainably.
👉 Contact us and let's take the next step together in your technological transformation.

Sebastián Sánchez

September 16, 2024