The problem statement
Enterprise software is often built with a three tier architecture: client-facing interface, the server-side application, and a relational database or other persistent storage module. When the client sends a request, the backend code or server side application processes the same by executing business logic, accessing the database to retrieve data and sending back the html views to the client browser; this server-side application is a monolith - single, logical & executable. Any changes to the system involve building and deploying a new version of the server-side application, even the smallest change requires that the entire system be rebuilt and redeployed.
In a large enterprise application, the monolithic code base creates a lot of complication in terms of code understanding, scaling becomes challenging, continuous integration/deployment becomes complex and often a daunting task. It's difficult to change technology or language framework because everything is tightly coupled and relies on each other.
Architect the server side application into a set of collaborating services. Basically the application is functionally decomposed into a set of services. Each service implements a set of narrowly, related functions. Thus changing a service implementation has no impact to other services as they communicate using well-defined interfaces.
In MSA (Micro Service Architecture), a software component is an independent running service that interacts with the other parts through message exchanging. Services are developed and deployed independently of one another. The data governance, data architecture is decentralised which minimise dependencies as a result of this each service has its own database in order to be decoupled from other services. The consistency between databases is maintained using either database replication mechanisms or application-level events. The independence of services helps with achieving high cohesion and loose coupling, which deliver all sorts of benefits (reliability, scalability, reusability, and so on)
Let’s visualize that we are building a store front like e-commerce application. In a monolithic application, we will have this as a single application consisting of Customer/Order Management, Catalog & Shipping Information. Now in case of Microservices the application should be functionally decomposed like Customer, Order Management, Catalog components are packaged as separate war files, each archive has its own database it can be relational, NoSql ,flat file etc. Each component will register with the service registry and can scale independently. This individual components need to talk to each other, it's quite common and it is achieved through pre-defined API. REST API can be used for synchronous or pub/sub for asynchronous communication, in our case the Order Components discovers Customer and Catalog service talks to them using the REST API. The Client Interaction for the application is defined in another application. The application mostly discover the services from service registry and compose them together. It should mostly be a dumb proxy where the UI pages of different components are invoked to show the interface
- Each Microservice is relatively small, leads to ease of development and maintenance
- This architectural pattern leads to truly scalable systems; Each service can be scaled independently of other services
- Easy to deploy and independent
- Fault diagnosis and isolation is easier, for example, a memory leak in one service only affects that service while other services continue to function normally
- No dependency towards a particular technology stack for a long time
- Developers must deal with the additional complexity of creating a distributed system
- Developers must implement the inter-service communication mechanism
- We need to have mature Dev Ops team for maintaining Microservices based application
- Implementing use cases that span multiple services without using distributed transactions is difficult
- Testing of such application is definitely harder when compared to monolith application
- Deployment complexity - In production, there is also the operational complexity of deploying and managing a system comprised of many different service types
- Increased resource consumption – Initial investment to run these applications are high
The microservice architectural style is an approach to develop a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.
The microservice architecture has a number of advantages. For example, individual services are easier to understand and can be developed and deployed independently of other services. It is also a lot easier to use new languages and frameworks because you can try out new technologies one service at a time. A microservice architecture comes with its own baggage and is not recommended for all projects. In particular, applications are much more complex and have many more moving parts. You need a high-level of automation, such as a PaaS, to use microservices effectively. You also need to deal with some complex distributed data management issues when developing microservices. Despite the drawbacks, a microservice architecture makes sense for large, complex applications that are evolving rapidly, especially for SaaS-style applications.