Building an Active/Standby HA Architecture with Queue-Based Microservices using Azure Functions
In recent years, the microservices architecture has gained traction owing to its remarkable scalability and adaptability. Azure Functions, a serverless compute service, facilitates the development of dynamic, scalable microservices. When designing microservices for enterprise systems, achieving high availability (HA) is crucial. This blog post delves into a strategy for constructing a HA architecture that incorporates queue-based microservices through the use of Azure Functions.
Challenges with Queue-Based Microservices
Creating HA queue-based microservices using Azure Functions comes with some design challenges. One of them is deciding between an Active/Active or Active/Standby architecture. While having an Active/Active architecture is trivial, it carries a cost from inter-region traffic and compute resources. Additionally, there may be scenarios where multiple consumers for the same queue are not necessary or desired, making Active/Standby a better option.
But there is a problem with Active/Standby for queue consumers, if more than one consumer is processing from a queue, they will both receive messages in a competing consumer mode. This makes it difficult to use Active/Standby in a failover mode where only one consumer is active, and the other is on standby. Unlike HTTP services where a load balancer like Azure Front Door can be used to solve the problem, a queue-based microservices architecture requires building custom mechanics to handle this scenario.
Approach to Building an Active/Standby HA Architecture
To address the challenges of building a HA architecture with queue-based microservices, let’s create a multi-region design that uses Azure Function Apps, a Health Check endpoint, and a Logic App. In my particular scenario, I have a multi-region setup with a primary and secondary region. The microservices are running by default in the primary one. In the event of a failure where the microservice dies or is unable to work in the primary region, the system needs to automatically start the service in the secondary region. After the primary region recovers its health, then it will stop or shut down the secondary region service and keep the primary region as the only active one.
The first step is to provide a Health Check endpoint, for this we will create an Azure Function App that exposes two functions. The first function is the one that consumes and processes messages from the queue (Queue Storage Trigger). The second function is a Health Check function (HTTP Trigger) that exposes the health of the service.
The second step is to provide auto-failover capabilities, we will build a Logic App that periodically monitors the Health Check endpoint for both copies of the consumer function. The Logic App will then start or stop the functions as needed. In the event of a failure, the Logic App can stop the primary function and activate the standby function. The logic app will detect when the primary region is available again and then switch over to the primary again, and shut down the secondary.
Building a high-availability architecture with queue-based microservices using Azure Functions is a good way to ensure your service remains highly available and scalable. By adopting a multi-region design that involves the use of Azure Function Apps, a Health Check endpoint, and a Logic App, we can create a robust architecture that can seamlessly process messages from queues, with Active/StandBy HA and auto-failover.