Design Patterns for Microservices
The design pattern will make your life easy even in the microservice development. There are number of design patterns exist to design the microservices. Some of them are,
✔Aggregator pattern,
✔Circuit Breaker pattern,
✔Proxy pattern,
✔API Gateway,
✔Branch,
✔Chain of Responsibility and so on.
In this article we are going to discuss about the first three design patterns related with the microservices.
🎇Aggregator Design Pattern
The Aggregator Pattern can have 3 types of sub design patterns as shown below. We will discuss one by one with the example.
For the easy of understanding, please refer the following scenario. You have 4 services along with the 2 consumers as shows below.
- Services: Service to get personal information, Service to get leave information, Service to get appraisal information and service to get project allocation information.
- Consumers: Attendance Management System, Project Management System.
✨Parallel or Scatter gather pattern
- Now the Attendance Management System need to get the personal details and leave information which are working independently.
- In order to get those information, what we can do is invoke the information from both independently working services in to new service aggregate them and send back to the consumer.
✨ Chain design pattern
- Let’s say our consumer Attendance Management System sends request to invoke the leave information from a particular employee along with the EmpId which is not consumed by leave information service. Instead of that leave information service does consume EmpCode. But it does have a dependency with the personal information service which has a field of EmpId.
- Now what we can do is invoke information from the first service in their you will have EmpCode. Then with these information, you will find the leave information as well.
- Then you can aggregate them and send back to the consumer.
✨ Service branch pattern
- Let’s say Project Management System requires personal details of employee along with his branch (which he is working at).
- Then the service request first go with the personal information service and then go to the specific branch service to collect his branch details.
- Likewise, by based on a decision, the service request can decide the path of branch.
- In this pattern, we need to consider more about the response time. For an example, if every services has their own validation mechanism to validate the response/request it will take time. But, if you have proper ID management system would be fine for your authentication and authorization mechanism.
🎇Circuit Breaker Pattern
Before going through the circuit breaker pattern, consider about the circuit in your home which controls the power in your home. You can see that, when power overloaded it got switched off automatically. That same thing is happening with the circuit breaker pattern as well.
Think you have 5 different services called A,B,C and D which are related with one another as below. Also in the thread pool you have 8 threads which called T1, T2, …, T8.
In this figure clearly shows that service A has more demand than the other service. In this situation, the service D is getting timeout (It is not responding for service request). That means service C is started to not working. Then, accordingly service B and A also will not working. That means our system is getting vulnerable and inefficient. In addition to that, the number of threads will be in and out of the thread pool. This kind of scenario is known as Cascading Failure.
In order to avoid the cascading failures, we can implement the Circuit-breaker pattern. Let’s see how we can implement the service breaker pattern.
At the beginning, we wanted to implement the threashold values for each service. For an example, service A should respond for any service request within 200ms.
If number of service requests (75% requests) reaches to the threashold value means the system is breaking slowly. When the response time exceeds 200ms we can treat this service as a not responding service. Then it immediately shows signal for other service requests before they are reaching to that service as service A is not working. Therefore, the thread pool will not get an additional queue during any failure time.
The Ping Request (Allows users to know particular service is back on online again) time to time to check whether the particular service is back on its normal state.
Once, the response time came back to the normal state, the service request will invoke the its desired services again.
🎇Proxy Design Pattern
Proxy pattern allows us to build the different services individually. Let’s discuss about this with our previous scenario which we discussed in the aggregator patterns.
If you follow agile approach in your development environment, you will get number of requirement changes in same or different domains in your application. In such a situation, it is your responsibility to keep the consumers system stable while making those changes. In your current application, to get the employee’s leave information, you pass the EmpCode instead of EmpId. Now you need to update your all the database schemas by having EmpId as a key to invoke the requested details. Now what will happen your consumers who has key as EmpCode instead of EmpId to invoke the services🤔🤔🤔. Now you and your consumer both get a trouble and consumer will be unhappy.
In such a situation, the Proxy design pattern comes in handy. In here, what really happens is it asks your service request to come through a proxy instead of directly hitting the services.
In your proxy service, initially can maintain the database schemas for both EmpCode and EmpId to invoke the services as shown below.
- When the request sends EmpCode, the proxy service will direct it to the Schema1 while the request with EmpId will send to the Schema 2.
- In this case you can have both version of services. That means you can independently deploy your services without interfering your consumers. When you realize, the Schema 1 does not get any request from your users anymore, then you can decommission it. In order to do that semantic versioning is very useful.
- In order to discover the all existing services and its versions for the customers, we can use Service Discovery Tool as a third party. When you have this, the service proxy will ask from it where the requested service is relying on.
- When you implement the proxy pattern make sure you will consider about the number of thread pools and efficient thread handover mechanism.
I hope you will get an clear idea about the some popular design patterns used in microservice architecture. Also, please follow the below references for further understanding.
Stay Safe !!!
References:
https://www.youtube.com/watch?v=DZeXqbFvYNA&list=PLD-mYtebG3X9HaZ1T39-aF4ghEtWy9-v3&index=5
https://www.youtube.com/watch?v=mw8W-RpvCu0&list=PLD-mYtebG3X9HaZ1T39-aF4ghEtWy9-v3&index=6
https://www.youtube.com/watch?v=7mBvb7nKONg&list=PLD-mYtebG3X9HaZ1T39-aF4ghEtWy9-v3&index=7
https://techblog.constantcontact.com/software-development/circuit-breakers-and-microservices/