What is Circuit Breaker?
Circuit Breaker Pattern is a programming pattern to resilient error handling.
When a service your application using is down or has no response, any further request to that service should be ignored. If an application trying to recovery unanswered service repeatedly, chances are that your application becomes unresponsive, too.
Create Circuit Breaker
At the code below, I implemented a circuit breaker using Polly.NET. Polly.Net is a library to implement application’s policies that keep an application from error propagation by resilient error handling.
return Policy
.Handle<HttpRequestException>()
.CircuitBreakerAsync(2, TimeSpan.FromMinutes(1), onBreak: (e, time) => {
System.Diagnostics.Debug.WriteLine($"Circuit has been closed due to exceptions during {time.Seconds}");
}, onReset: () => {
System.Diagnostics.Debug.WriteLine($"Circuit is restored");
});
Store Circuit breaker instance
Because Polly remembers failure count only per instance, the circuit doesn’t closed until you save and reuse instance.
private static Lazy<IAsyncPolicy> circuitBreaker = new Lazy<IAsyncPolicy>(() => { ... }
Request HTTP client
With the circuit breaker instance created beforehand, the code below creates an HTTP request using HTTPClient class. It requests {WebApiApplication.ApiConfig.api} to server via GET method.
When WebApiApplication is down and this code tries two or more times with 1 minute, Policy will close the circuit and cut any following execution.
var client = new HttpClient();
var result = await circuitBreaker.Value.ExecuteAsync((ct) => {
var request = new HttpRequestMessage(HttpMethod.Get, new Uri(
$"http://{WebApiApplication.ApiConfig.host}:{WebApiApplication.ApiConfig.port}/{WebApiApplication.ApiConfig.api}/{id}"
));
return client.SendAsync(request, ct);
}, System.Threading.CancellationToken.None);
return result;
In this sample code, I doesn’t use HTTP client pooling, but I highly recommend you to use HTTP client pooling. Without HTTP connection pooling, your application will use up every socket connection resource.
For more detail, I recommend you to read more about TIME_WAIT.
Whole sample code
private static Lazy<IAsyncPolicy> circuitBreaker = new Lazy<IAsyncPolicy>(() => {
return Policy
.Handle<HttpRequestException>()
.CircuitBreakerAsync(2, TimeSpan.FromMinutes(1), onBreak: (e, time) => {
System.Diagnostics.Debug.WriteLine($"Circuit has been closed due to exceptions during {time.Seconds}");
}, onReset: () => {
System.Diagnostics.Debug.WriteLine($"Circuit is restored");
});
});
// GET api/values/5
public async Task<HttpResponseMessage> Get(int id)
{
var client = new HttpClient();
var result = await circuitBreaker.Value.ExecuteAsync((ct) => {
var request = new HttpRequestMessage(HttpMethod.Get, new Uri(
$"http://{WebApiApplication.ApiConfig.host}:{WebApiApplication.ApiConfig.port}/{WebApiApplication.ApiConfig.api}/{id}"
));
return client.SendAsync(request, ct);
}, System.Threading.CancellationToken.None);
return result;
}