Essentials of Microservices

Microservices have gained immense popularity in Software Development in the last few years as they provide many benefits for Agile and DevOps teams. 🤗
Netflix, eBay, Amazon, etc have all evolved from monolithic to microservices architecture. 😮

Unlike microservices, a monolith application is built as a single, autonomous unit. This makes changes to the application slow as it affects the entire system. A modification made to a small section of code might require building and deploying an entirely new version of the software. Scaling specific functions of an application, also means you have to scale the entire application.

Microservices solve these challenges of monolithic systems by being as modular as possible. In the simplest form, they help build an application as a suite of small services, each running in its own process and are independently deployable. These services may be written in different programming languages and may use different data storage techniques. While this results in the development of systems that are scalable and flexible, it needs a dynamic makeover

Of course, no technology is a silver bullet, while Microservices come with several benefits, they also bring several issues that need to be addressed which is rather less difficult in Monoliths 🤨 to list a few :

On what basis do you split/decompose application into different services?

How does communication happen between them?

How is the data consistency maintained?

How is Authentication & Authorization implemented across the application?

How are the Services deployed & monitored to reduce downtime?

In this blog, I’ll try talking briefly about some of them, let’s get started

1. Decomposing application into Services :

  • Services are loosely coupled
  • Teams that work on one or more services stay autonomous with minimal collaboration with other teams
  • Each Service is small enough to be maintained/developed by a team
  • Services must conform to the Common Closure Principle — things that change together should be packaged together

Decompose by Business capability

  • Identifying Business Capabilities — which is done by understanding the organization’s purpose, structure & business processes
  • Define serviceseach identified business capabilities or a group of them could be mapped to a service

A sample mapping of the capability of Food delivery business to architecture service could be

A key benefit of organizing services around capabilities, which are stable, is that the resulting architecture will be relatively stable. The individual components of the architecture may evolve as aspects of the business change, but the architecture itself remains unchanged.

Decompose by Sub-domain

It comprises of steps as shown

2. Communication between services :

However, replicating the same in a distributed environment using RPC(Remote Procedure Call) for all communication could result in a lot of in-efficiency and since a microservices-based application is a distributed system running on multiple processes or services. Each service instance is typically a process. Therefore, services must interact using an inter-process communication protocol such as HTTP, AMQP, or a binary protocol like TCP, depending on the nature of each service. There could be many ways clients & services could communicate, each one suitable for different scenarios. The types of communications can be classified into two axes.

The first axis defines if the protocol is synchronous or asynchronous:

  • Synchronous: HTTP is synchronous, meaning the client sends a request & waits for a response irrespective of code execution on the client (sync or async) which clearly means that client code can only continue its task when it receives the HTTP server response. REST is a popular architectural style
  • Asynchronous: This protocol uses Messaging-based communication. This is the most popular choice to make the integration loosely coupled and asynchronous, also make our application resilient and scalable. We usually use a message broker to manage and process the message sent by the producer and it can be persisted if required; the message broker will guarantee message delivery to the Consumer. This makes the communication asynchronous. There are two options one being Point-to-Point & the other Publisher-Subscriber. Apache Kafka, RabbitMQ, ZeroMQ are few examples

The second axis defines if the communication has a Single receiver (or) Multiple receivers

When to use what? Here are my suggestions

  • Use REST For communication between browser & your service or provide public API
  • For communication between internal services try to model your processes using messages, if not possible then choose gRPC or Event/Message Driven mechanism
  • When dealing with high volumes of messages via HTTP or If you find latency or network saturation to be any sort of bottleneck, consider adopting RPC

Remember the more you add synchronous dependencies between microservices, such as query requests, the worse the overall response time gets for the client apps! 😑

3. Data management :

The Data-per-Service pattern

The Saga pattern

When a customer places an order in an eCommerce store, the two services called customer service and order service will be working. When a customer service sends the order, the order will be in the pending state. The saga contacts the eCommerce store through the order service and will manage the placing of events. Once the order service gets the confirmation about the order, it sends the reply.

Depending on the reply, the saga will approve or reject the order. The final status of the order is presented to the customer stating that the order will be delivered or having the buyer proceed to the payment method. In cases where the order is not accepted by the eCommerce store, it sends an apology message or shows the out-of-stock indicator.

The CQRS pattern

CQRS suggests splitting the application into two parts — the command side and the query side. The command side handles the Create, Update, and Delete requests. The query side handles the query part by using the materialized views. The event sourcing pattern is generally used along with it to create events for any data change. Materialized views are kept updated by subscribing to the stream of events. 🥱

Woof ! That was long anyways Glad that you reached here 😇 , there’s a lot more to discuss 😅 but don’t worry I won’t go beyond this. I’ll leave it for the next part 😁.

If you enjoyed this article, share it with your friends and colleagues!

Additional Resources and Tutorials on Microservices

We are business accelerator working with startups / entrepreneurs in building the product & launching the companies.