Let us take a look at a popular architectural pattern known as ‘Microservices’.
The Definition of Microservices by Adrian Cockcroft is as below: "Loosely coupled service oriented architecture with bounded contexts".
Microservice is an architectural pattern wherein we develop small, manageable services with a well-defined API and which are independently deployable. Each of the Microservices typically will be backed by its own database. So in essence, every microservice is an application in its own. This is in contrast to the traditional monolithic applications. Monolith, as the name implies is a single huge application, which has tightly coupled modules. Traditionally we used to build applications as a monolith, i.e., the entire application is packaged as one single deployable unit. For instance in the J2EE world, the deployable unit used to be a large EAR/WAR file and one single large database.
Why do need microservices?
1. Roll out features quickly to production:
The customer might need minor changes to functionality which should be rolled out at the earliest, as they have a higher business impact. Microservices enable us to make small iterative changes, test and deploy those changes quickly to production.
2. Ease of maintaining and adding functionality:
With loosely coupled microservice architecture, each service is loosely coupled to other services and each service would have a well-defined boundary (which is known as bounded context). This allows for each service to independently evolve and it would be easier to add new features to individual microservices. This makes the overall system easier to maintain from a functional standpoint. In a traditional monolithic application, there could be a lot of tight coupling amongst modules and adding new features could sometimes be nightmarish.
3. Scale out the application based on modules:
Very often we observe that few modules of our application face a huge load compared to others. We might want to dedicate more resources to these modules instead of scaling out the entire application. However, in a monolithic application, we may not be able to do this at a module level (since we have a single huge deployable unit), thus ending up wasting money/resources by scaling the entire application. However, with microservices, we can scale individual services easily, thereby saving compute/memory resources.
4. Flexibility to choose the right database, also known as Polyglot Persistence:
With microservices architecture, we can choose the right database flavor for the right service. In a monolith, generally, we will be forced to retrofit our design to fit the database which is already chosen for the application. However, in a microservice, we have the liberty to select the right database which fits the requirement. For instance, in an Ecommerce application, a microservice which provides Product Reviews as a service, might chose a NoSQL database like Mongo DB to store the reviews.
5. Flexibility to choose the right programming language, also known as Polyglot Programming:
With microservices architecture, we can choose the right programming language which fits the requirement. One service could be written in Ruby, while other in Python and so on.
An Ecommerce application could be composed of multiple microservices as below:
- Service for Product Catalog
- Service for Customer Profile
- Service for Product Reviews
- Service for Shopping Cart
- Service for Order Fulfillment
If each of these services is exposed through a well-defined API, then changes to the individual services could be made quickly and rolled out quickly (as long as they don’t change the API interface).
Challenges posed by Microservices Architecture:
Let us take a look at the challenges which we would face while adopting Microservices Architecture. Not everything is simple with Microservices. It comes with a baggage of its own problems.
- Service Discovery
- Deployment challenges
- Database challenges
- API Management
- Integration Testing
- Fault Handling