Sunday, May 7, 2023

Microservices with Kotlin - Cloud Native Microservices

 Understanding Microservices 

Microservices and their continuously evolving architecture have become one of the most used approaches in enterprise applications. I will try to get an understanding of what they really are and the principles that they are based on. Using Domain-Driven Design, we will reinforce those principles to maintain a clean architecture that can evolve with our applications. Since microservices have no static architecture, we will discover how the new reactive paradigm could change the way we create them. And, finally, we will have an overview of cloud architecture and why we should create Cloud Native microservices. you will learn about: 

What a microservice really is Understanding microservices principles . 

Using Domain-Driven Design for a clean architecture 

Non-blocking reactive microservices

Cloud Native microservices and their benefits

What is a microservice? 

Microservices are modular, loosely-coupled services that provide a fine-grained protocol. They physically separate concerns and allow us to design, develop, test, and deploy them independently. Due to their modular capabilities, they can be created by small cross-functional teams that are embracing the benefits of agile methodologies and the DevOps culture. They are also an ideal candidate for continuous delivery and deployment. DevOps is a software development and delivery process that emphasizes communication and collaboration between product management, software development, and operations professionals. They are easy to understand and connect well with other services, making integration of complex applications a lightweight task. They can be scaled, monitored, and controlled independently so that they fully benefit cloud architectures.

Understanding SoA

Microservices are an evolution of the Service Oriented Architecture (SoA). So, if we want to understand what a microservice is, we need to understand what SoA is. SoA is based on having application components communicating through a set of services, a discrete unit of functionality that can be accessed remotely. Services are the foundation stone in SoA, and the same applies to microservices as well. As described in SoA, a service has four properties: It logically represents a business activity with a specified outcome It is self-contained It is a black box for its consumers It may consist of other underlying services To understand these properties, let's look at an example of an application using SoA:



In this typical n-tier architecture, the application is divided into three layers:

Presentation layer: Holds the UI for our customer 

Business layer: Has services implementing the domain logic for our business capabilities

Data layer: Persists our domain model

 Each component includes the logic to interact with the customer in a specific business activity and to do so, uses the services provided by the business layer. Each service represents the realization of a business activity. For example, you log in to the application provided by the login service, check offers provided by the offers service or create orders via the orders service. These services are self-contained in the business layer, and they act as a black box for their consumer—the components don't know how the services are implemented, nor do they know how the domain model is persisted. All the services depend on the customer service to obtain customer data, or return customer information, but the client does not know about these details. This approach provides several benefits to any architecture that uses it: Standardized service contract, allowing easy integration with components Reusability, allowing services to delegate responsibilities to each other Business value, implementing the business capabilities Hides complexity; if we need to change our database, the clients are unaffected Autonomyl; each of the layers could be separated and be accessed remotely.

 Differentiating microservices from SoA

Microservices architecture evolves from SoA, but it has key differences that we need to understand. Let's recreate the previous SoA example with a microservices architecture and eview the differences and benefits for this type of architecture:


In this architecture, the layers are not bound together, as they are purely divided logically. Each microservice is completely decoupled from the other services, so even our UI components could be completely separate, deployable modules. These microservices own their own data and they could be altered without affecting each other. This is a capability that will stand out when facing continuous integration or delivery, as we could provision data for our tests and pipeline, without affecting other parts of the application. Because of their independence, they could be very specific. We could use this benefit to build that expertise into our teams. An expert team that controls the domain logic from a business capability could effectively deliver better value to our products. We could vary the range of development languages, platforms, or technologies to build each microservice. As they are completely independent, we could use a different database for each different business need, or perhaps use certain technologies that will give us the agility required to adapt to certain requirements more easily. Since they are modular, we could deploy them independently and have different release cycles. When we need to monitor them, we could create different alerts or KPIs based on the nature of what they do and how they are done. It may not be the same for a microservice used in our accounting process as one that just provides content for our marketing banners. For similar reasons, we could scale them separately; we could have more servers for some microservices, or just more CPU or resources for others. 

Taking advantage of how we can control and monitor microservices independently will grant us the ability to optimize scaling.

The infrastructure for microservices is usually simpler, as there are not as many complex servers to manage, configure, monitor, and control, no huge database schemas and, since the expertise within the teams is higher, more things can be easily automated. This will make DevOps culture within microservices teams a common practice, and with it we will gain even more flexibility within our products. As microservice teams are usually small, there is a common understanding within the industry that the optimal size for a microservice team is one that could be fed with two pizzas. Whether or not this is the reality, keeping your team small will help to maximize the value of this type of architecture. If we look at SoA and then microservices, what we can see is a natural evolution. Microservice architecture takes the advantages of SoA and then defines additional steps in that same direction.

So, we can definitely say that: "Microservices are SoA but all SoA are not microservices."

From the monolith to microservices

 So, why did SoA evolve into microservices? Perhaps one of the reasons was due to the monolith. There was a point in time where applications were small, and the presentation logic was usually coupled with the business logic. Then, the domain model got complex and many software patterns arose. Most of them were focusing on one thing: Separation of Concerns. Separation of Concerns (SoC) is a design principle for separating software into distinct sections so that each section addresses only one concern. But software is not the only thing that needs separation; the architecture needs it as well. Things like SoA are designed for that, as it allows us to hide our complexity behind black boxes to make our architecture more modular, and with the ability to handle the complexity that we require. We may create a complex data store in the mainframe based on detailed business rules, or on a powerful database with a deep schema, complex stored procedures, views, and relationships. We can choose frameworks and tools to easily orchestrate all these parts. We probably also need a powerful Enterprise Software Bus (ESB). An ESB is a software component that is in charge of the coordination, mapping, and routing of services. The overall idea is to have a very powerful component to easily orchestrate messages. In order to create complex applications, services were designed using most of these elements, creating complex relationships. From services calling each other, to views querying several tables, pulling data from different business domains. And finally, merging in our ESB several of those elements with business rules to produce new services.

Even scaling the application could be affected, whether it's a bigger database, more servers for services, a bigger ESB for handling more messages. Since they depend on each other, it is not easy to scale them separately. All of this means that our architecture is coupled and we have created a monolithic application. Monolithic applications existed before SoA and, in fact, this was one of the things that SoA helped to handle, decoupling the clients from the business domain. Unfortunately, trying to implement SoA drove many applications back to it. Does this mean that doing SoA will produce a monolith? No. In fact, before the concept of microservices, many architects and developers started to adopt patterns and architectures to handle this problem. This evolved into what we call microservices today. There were people doing microservices before that name existed; they just called it SoA.

No comments: