Microservice architecture
Before we look at the microservice architecture, let's look at how web applications were built before that. The traditional way of building software applications was called monolithic architecture. Enterprises used to develop applications as one big indivisible unit that provided all the intended functionality. In the initial phases of development and deployment, monoliths offered some fairly good advantages. Project planning and building a minimum viable product – the alpha or beta version – was easier. A single technology stack would be chosen, which made it easier to hire and train developers. In terms of deployment, it was easier to scale since multiple copies of this single unit could be thrown behind a load balancer to scale for increased traffic:
Figure 1.3 – Monolithic architecture
The problem starts when the monolithic application has to accommodate more features and the business requirements grow. It becomes increasingly complex to understand the business logic and how the various pieces that implement the features are interconnected. As the development team grows, parts of the application will be developed by dedicated teams. This will lead to a disconnect in communication and introduce non-compatible changes and more complex dependencies. The adoption of new technologies will become virtually impossible and the only choice to bring in changes that align with changing business requirements would be to rewrite the application in its entirety. On the scaling front, the problem is that we need to scale up the entire application, even if only a particular piece of code or business logic is creating the bottleneck. This inflexibility causes unnecessary provisioning of resources and idle time when the particular business logic is not in the critical path.
The microservice architecture was introduced to fix the shortcomings of the monolithic architecture. In this architecture, an application is organized as a collection of smaller independent units called microservices. This is achieved by building separate services around independent functions or the business logic of the application. In a monolithic architecture, the different modules of the application would communicate with each other using library calls or inter-process communication channels. In the case of the microservice architecture, individual services communicate with each other via APIs using protocols such as HTTP or gRPC. Some of the key features of the microservice model are as follows:
- Loosely coupled – each unit is independent.
- Single responsibility – one service is responsible for one business function.
- Independently develop and deploy.
- Each service can be built in a separate technology stack.
- Easier to divide and separate the backends that support the services, such as databases.
- Smaller and separate teams are responsible for one or more microservices.
- The developer's responsibilities are better and clearly defined.
- Easy to scale independently.
- A bug in one service won't bring down the entire application. Instead, a single piece of business logic or a feature would be impacted:
Figure 1.4 – E-commerce application with the microservice architecture
While microservices help solve a lot of problems that the monolithic architecture posed, it is no silver bullet. Some of the disadvantages of microservices are as follows:
- Given all inter-microservice communication happens via the network, network issues such as latency have a direct impact and increase the time it takes to communicate between two parts of the business function.
- Since most business logic requires talking to other microservices, it increases the complexity of managing the service.
- Debugging becomes hard in a distributed microservice environment.
- More external services are required to ensure visibility into the infrastructure using metrics, logs, and tracing. The absence of any of this makes troubleshooting hard.
- It puts a premium on monitoring and increases the overall infrastructure cost.
- Testing global business logic would involve multiple service calls and dependencies, making it very challenging.
- Deployments require more standardization, engineering investment, and continuous upkeep.
- It's complex to route requests.
This sums up the microservice architecture and its benefits. In the next section, we will briefly discuss a few technologies that can help microservices be deployed more structurally.
Containers, orchestration, and microservices
Containers revolutionized the way we deploy and utilize system resources. While we had microservices long before containers became popular, they were not configured and deployed optimally. A container's capability to isolate running processes from one another and limit the resources that are used by processes was a great enabler for microservices. The introduction of container orchestration services such as Kubernetes took this to the next level. It helped support more streamlined deployments and developers could define every resource, every network, and every backend for an application using a declarative model. Currently, containers and container orchestration are the de facto way to deploy microservices.
Now that we have a firm understanding of the microservice architecture, let's examine another architecture pattern – EDA.