Circuit Breaker in Microservices Architecture :
In this article, we will be covering what a circuit breaker is, its different states and why it is widely used in the microservice architecture. We will also see a practical example that shows its use in a concrete situation.
What is a circuit breaker :
Whenever we call a service, a thread is assigned to serve each request :
If an error occurs when the service receives the first request and for example can’t find it,the first thread will be blocked and won’t proceed since it is waiting for an answer from the requested service. Then a second error occurs for the second request and the second thread is blocked as well. What if there was too many errors in the requested service, and all the threads are blocked waiting for a response? well it causes a Timeout failure.
Since none of the threads in the thread pool are available, the calling service won’t be able to handle any more request. Therefore the failure would have spread from the requested service to the calling service. It can continue spreading into each service until causing a general failure.
To prevent that from happening, we use circuit breakers ! They stop errors from spreading between services. When a max number of failures are reached ( it can be configured in the application.conf file with max-failure ) the circuit breaker goes to an open-state, which won’t allow any more requests to be sent to the requested service during a certain period of time named call-timout( can be found in the conf file as well ).
Once the timout elapsed the circuit breaker is on half-open state, it takes the first request that was sent, assigns a thread to it, and if it succeeds it goes back to its normal state closed. If not the circuit breaker goes back to the open state for another timeout.
Note : In many fameworks, errors such as 404 and 422 are considered as failure, which means that they can cause a circuit breaker to be on open state, which isn’t worth provoking such a reaction. To stop that from happening, it is possible to configure a White-List, which is a list of error types that should be ignored and that won’t lead to circuit breaker. It is configured on the application.conf file.
Example :
In what is coming we will see a simple example of a circuit breaker :
Let’s take the example of MyPen, a firm that sells various types of pens in large quantities. It has 4 main services : ordering, stock, payment and shipping. a certain company wants to make an order of 10 peaces of 100 different pens.
the payload looks like this :
{
Client : Rkejji,
category : swissBold,
productId : 11223344,
quantity : 433
}
Once the ordering service receives the requests it has to make a call to the stock service to insure that for each type of pen, the quantity ordered is available. Once it is done, it sends a request to the shipping service with the quantity and product to deliver finaly after some days the payment service sends an email to the client to ask for the money !
To call the stock Service it looks like this in Scala :
orders.map { order =>
stockService.findOrderInStock(order.category, order.quantity)
}def findOrdersInStock() : Future[ProductSatus]
Now what if, for some reason, we can’t find the category of all the orders in the stocks, the function findOrdersInStock returns a NotFound exception for each request that was sent. Since we have 10 threads, after 10 failed requests, the Order service can send no more requests.
Therefore, all the other requests of any other client that was sent by the Order service to any other service are blocked. Some of the requests sent to the Order service that have nothing to do with the Stock service will fail, and this implies that until all the services fail.
When using a circuit breaker, once the number of errors reaches a max-failures number, the circuit-breaker is open, all the requests from the Order service to the Stock service are put aside for a call-timeout ( usually 60 seconds). So the Order service can still send requests to other services.
After 60 seconds, the circuit breaker is half-open, it takes the first request and serves it, if it succeeds everything is back to normal, if not it goes back to the open state.
Conclusion :
- Circuit breakers are here to prevent failures from spreading between the services until it causes a general failure
- Circuit breakers have 3 states: open, half-open and closed
- Circuit breakers are on open state when the number of failures reaches the max-failure parameter
- Circuit breakers are open for a certain lapse of time, after what it goes to a half open state. Then the latest request is served, if it succees, the circuit breaker goes back to its normal state (close). If not it goes to an open state for another lapse of time
- In most frameworks, the exceptions 4xx and 5xx are considered as errors and can cause a circuit breaker to be open, some of those errors are not worth to cause an open circuit break, it is possible to add them to a white list : which is a list of errors that are to be ignored by the compiler.