Implementing circuit breaker

Implementing the retry pattern is a good practice when calling services that are communicating over a network. However, the calling mechanism itself takes resources and bandwidth to execute the operation and delay the response. If the services are already in a faulted state, it is not always a good practice to retry it multiple times for every request. This is where circuit breaker plays its role.

Circuit breaker works in three states, as shown in the following diagram:

Initially, the circuit breaker is in a Closed State, which means the communication between services are working and the target remote service is responding. If the target remote service fails, the circuit breaker changes to Open State. When the state becomes open, then all subsequent requests cannot invoke the target remote service for a particular, specified time, and directly returns the response to the caller. Once the time elapses, the circuit turns to Half-open State and tries to invoke the target remote service to get the response. If the response is received successfully, the circuit breaker changes back to Closed State, or if it fails, the state changes back to closed and remains closed for the time specified in the configuration.

To implement the circuit breaker pattern, we will use the same Polly framework, which you can add from the NuGet package. We can add the circuit breaker policy as follows:

var circuitBreakerPolicy = Policy.HandleResult<HttpResponseMessage>(result => !result.IsSuccessStatusCode) 
  .CircuitBreakerAsync(3, TimeSpan.FromSeconds(10), OnBreak, OnReset, OnHalfOpen); 

Add the preceding circuit breaker policy inside the ConfigureServices method in the Startup class. The reason for defining it in the Startup class is to inject the circuit breaker object as a singleton object through Dependency Injection (DI). Therefore, all requests will share the same instance and the state will be maintained properly.

While defining the circuit breaker policy, we set the number of events allowed before breaking the circuit as three, which checks how many times the request has failed and breaks the circuit once it reaches the threshold value of three. It will keep the circuit break Open for 10 seconds and then change the state to Half-Open when the first request comes in after the time has elapsed.

Finally, if the remote service is still failing ,the circuit state changes to the Open state again; otherwise, it is set as Close. We have also defined OnBreak, OnReset, and OnHalfOpen delegates that are invoked when the circuit state changes. We can log this information somewhere in the database or file system if required. Add these delegate methods in the Startup class:

private void OnBreak(DelegateResult<HttpResponseMessage> responseMessage, TimeSpan timeSpan) 
{ 
  //Log to file system 
} 
private void OnReset() 
{ 
  //log to file system 
} 
private void OnHalfOpen() 
{ 
  // log to file system 
}

Now, we will add the circuitBreakerPolicy and HttpClient objects using DI in the ConfigureServices method in the Startup class:

services.AddSingleton<HttpClient>(); 
  services.AddSingleton<CircuitBreakerPolicy<HttpResponseMessage>>(circuitBreakerPolgicy);

Here is our UserController that takes the HttpClient and CircuitBreakerPolicy object in the parameterized constructor:

public class UserController : Controller 
{ 
  HttpClient _client; 
  CircuitBreakerPolicy<HttpResponseMessage> _circuitBreakerPolicy; 
  public UserController(HttpClient client, 
CircuitBreakerPolicy<HttpResponseMessage> circuitBreakerPolicy) { _client = client; _circuitBreakerPolicy = circuitBreakerPolicy; } }

And this is the HTTP POST method that uses the circuit breaker policy and invokes the email service:

// POST api/values 
[HttpPost] 
public async Task<IActionResult> Post([FromBody]User user) 
{ 
 
  //Email service URL 
  string emailService = "http://localhost:80/api/Email"; 
 
  //Serialize user object into JSON string 
  HttpContent content = new StringContent(JsonConvert.SerializeObject(user)); 
 
  //Setting Content-Type to application/json 
  _client.DefaultRequestHeaders 
  .Accept 
  .Add(new MediaTypeWithQualityHeaderValue("application/json")); 
 
  //Execute operation using circuit breaker 
  HttpResponseMessage response = await _circuitBreakerPolicy.ExecuteAsync(() => 
_client.PostAsync(emailService, content)); //Check if response status code is success if (response.IsSuccessStatusCode) { var result = response.Content.ReadAsStringAsync(); return Ok(result); } //If the response status is not success, it returns the actual state
//followed with the response content return StatusCode((int)response.StatusCode, response.Content.ReadAsStringAsync()); }

This is the classic circuit breaker example. Polly also comes with an advanced circuit breaker, which is more useful in cases where you have to break the circuit based on the percentage of failed requests in a particular amount of time. When working with big applications or applications that involve lots of transactions within a minute, there's a chance that 2% to 5% of transactions will fail due to other non-transient failure issues, so we don't want the circuit to break. In this case, we can implement the advanced circuit breaker pattern and define the policy in our ConfigureServices method, which is shown as follows:

public void ConfigureServices(IServiceCollection services) 
{ 
    
  var circuitBreakerPolicy = Policy.HandleResult<HttpResponseMessage>(
result => !result.IsSuccessStatusCode) .AdvancedCircuitBreaker(0.1, TimeSpan.FromSeconds(60),5, TimeSpan.FromSeconds(10),
OnBreak, OnReset, OnHalfOpen); services.AddSingleton<HttpClient>(); services.AddSingleton<CircuitBreakerPolicy<HttpResponseMessage>>(circuitBreakerPolicy); }

The first parameter in the AdvancedCircuitBreakerAsync method contains a value of 0.1, which is the percentage of requests that have failed in the time frame, which is 60 seconds, as specified in the second parameter. The third parameter which, defines the value of 5, is the minimum throughput of requests being served in that particular time, as specified in the second parameter which is 60 seconds. Finally, the fourth parameter defines the amount of time the circuit remains open if any request fails and tries to serve the request again once the time has elapsed. The Other parameters are just delegate methods that are called when each state is changed, which is the same as in the previous classic circuit breaker example.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.98.239