Microservice Design Patterns (Part — 03)
The proxy microservice design pattern is slightly similar to the aggregator. But according to the proxy design pattern, we do not need an aggregator on the consumer, but we create a microservice to invoke other services based on the business requirements. Let’s understand the proxy pattern with the below example.
▪ ️Assume your company currently having a monolithic application. So now you need to move to microservice architecture. So when you are deploying microservices maybe you need to change the services.
▪️ Consider, you have a microservice to get the leave information of employees. So the consumers need to pass the empCode to get leave information. (Figure1)
▪️ But with the new restructure, you have decided to keep empID as a relational key for all the records.
▪️ So now you deployed your new restructured Employee service (New version). But unfortunately, the consumers who are already consuming your previous service of Employee Service will break.😭
▪️ Because those consumers will pass the “empCode”. But the newer version of the service needs the empID. So at the time, you update the current service to the new version, your consumers will break.
🟡 As a solution for this, we can use the Proxy Design pattern here.
▪️ You can solve this by creating a separate proxy service as shown below. (Figure 2)
▪️ Accordingly, the consumers will invoke the Proxy service. And you can modify it as (Figure 3):
If the consumer passes the empID ➩ call version 2 (New version)
If the consumer passes the empCode➩ call version 1(Old version)
✹ So in this way, you can independently deploy the service without affecting the consumer. When there’s no traffic, and schema 1 does not receive requests from the consumers, you can decommission service 1 and keep service 2 (new version). Here, semantic versioning is much important.
✹ However, there are other important things we have to consider when talking about the Proxy design pattern.🡻
Semantic versioning shows each of the releases by three non-negative integers as “MAJOR.MINOR.PATCH” (as shown in Figure 4)and each of these integers has its own meaning.
▪️ I have discussed versioning in my “Best Practices for Microservices” blog. Please refer to it for more details. (Click the link below)
✨ Service Discovery
✹ It’s better to use an external party to discover your service when you create a service.
Because, If the infrastructure gets changed in a microservices-based system, the hostname, IP addresses …etc. can also be changed. . To keep safe, the consumers need a way to identify the instances of the available service. So if you have a service discovery tool, the proxy can invoke the service discovery tool and can get the updated addresses. So this is the way the service discovery comes in.
Examples for some service discovery tools: WSO2 Governance Registry, CONSUL by Hashicorp, Zookeeper, SmartStack…etc.
Notes 📝 :
✤ When you are implementing a proxy pattern, you need to pay attention to thread pools. Because threads can get blocked if you did not implement a proper thread pool functionality. (It’s better to use multiple thread pools or thread handover mechanisms accordingly)
✤ The proxy is placed in between the consumer & the new microservices (the newly created version of microservice). The proxy preserves the original API, thereby it permits consumers to interface with it. The proxy service has the required logic to join with the new microservices to supply the data and original logic to the consumers.
✨ Time outs
When you have a proxy service and assume that the service version 1.0 is getting delayed. Accordingly, if you do not have implemented “time-out”, it can block the thread and can affect the new service version 2.0 too.
I have discussed time-outs in the blog “Circuit Breaker Pattern”. Please refer to it for more details. (Click the link below)
Advantages and disadvantages of Proxy design pattern
✹ It is easy to implement.
✹ Validations and security associated with external service can be implemented and can be encapsulated very easily in a proxy.
✹ Unsuitable change of response