In a microservices environment, usually, multiple services talk to each other either. Some cases through HTTP calls, whereas in other cases using an event bus or queues. Circuit Breaker is an important pattern which helps to make microservices more resilient in these communication patterns.
When services communicate with each other through HTTP calls, there is always a possibility of failure. One service might fail or HTTP connection might break due to network error. In these scenarios creating a resilient service is extremely important. And circuit breaker is a pattern
Reactive communication through Queue and Event bus also might fail, buts its extremely rare compared to the HTTP call.
What is Circuit Breaker?
Circuit Breaker is a design pattern, where you try a service call for a configured number of times. And if the service call fails consecutively for the configured number of times, you just open the circuit.
Why is it important?
System resources like threads and I/O are very important. When an external service continuously fails, there is no need to spend these resources in calling out to that service. Instead, you wait and give the external service to
Implementing on your own
We can implement the Circuit Breaker on our own. In the catch block of a service call, we can implement static counter per service endpoint. And increment for every consecutive failure. And which the count received the configured number of allowed failure we can set a Boolean which will return the subsequent calls whiteout actually making an HTTP call out. Finally, reset the flag based on a timer.
But, that’s a lot of code and testing that logic out. When Polly supports all these, we would rather focus on our business logic and let Polly do the magic.
Implementing Circuit Breaker with Polly
I created a Web API in my last blog “Auto retry with Polly”, where the service call always throws a
The code for the Error API:
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
namespace ErrorApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
throw new Exception("Error");
}
}
}
Firstly, I will create a new ASP.NET Core Web API.
Secondly, I will update the class ValuesController
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace CircuitBreaker.Demo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IHttpClientFactory httpClientFactory;
public ValuesController(IHttpClientFactory httpClientFactory)
{
this.httpClientFactory = httpClientFactory;
}
// GET api/values
[HttpGet]
public async Task<ActionResult<IEnumerable<string>>> Get()
{
var client = httpClientFactory.CreateClient("errorApi");
var response = await client.GetAsync("api/values");
return JsonConvert.DeserializeObject<string[]>(await response.Content.ReadAsStringAsync());
}
}
}
Thirdly, I will add the NuGet package Microsoft.Extensions.Http.Polly
to support Polly.
Fourthly I will update the classStartup
to configure HttpClientFactory
Error API endpoint.
services.AddHttpClient("errorApi", c => { c.BaseAddress = new Uri("http://localhost:5000"); });
Finally, I will configure Circuit Breaker with Polly for HttpClientFactory
.
using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Polly;
namespace CircuitBreaker.Demo
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddHttpClient("errorApi", c => { c.BaseAddress = new Uri("http://localhost:5000"); })
.AddTransientHttpErrorPolicy(p => p.CircuitBreakerAsync(2, TimeSpan.FromMinutes(2)));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
}
Testing the Application
When I run and test the application, I will see that the service will open up the circuit and throw the circuit breaker exception after 2 consecutive failures.
Conclusion
In conclusion, Polly makes is really easy to implement the circuit breaker pattern. And since all the configuration is done in the classStartup
the actual code where we make the service call is very clean.
YouTube link for the entire session is here: https://www.youtube.com/watch?v=ScpydLKqQuQ