IConfiguration vs IOptions NET
Synchronous and Asynchronous in .NET Core
Model Binding and Validation in ASP.NET Core
ControllerBase vs Controller in ASP.NET Core
ConfigureServices and Configure methods
IHostedService interface in .NET Core
ASP.NET Core request processing
| Circuit Breaker Pattern in .NET | OCR In ASP.NET | |
Retry Pattern in .NET Core |
The Retry pattern is a design pattern used to handle transient faults that occur when an application interacts with a remote service or resource. A transient fault is a temporary, self-correcting error, such as a brief network glitch, a database connection being temporarily dropped, or an external service being momentarily busy.
Instead of immediately failing and returning an error, a retry pattern automatically re-attempts the failed operation a specified number of times with a defined delay between attempts. This enhances the application's resilience and improves the user experience by transparently recovering from minor issues.
In .NET Core, the Polly library is the standard for implementing various resilience patterns, including Retry. It provides a fluent, thread-safe way to define these policies.
Retry patterns are used to handle transient faultsβtemporary issues like network glitches, timeouts, or service unavailabilityβthat often resolve themselves. Instead of failing immediately, the application retries the operation after a short delay, improving resilience and user experience.
The most common and robust way to implement a retry policy in ASP.NET Core is by integrating Polly with IHttpClientFactory, which is available since .NET Core 2.1.
The Polly library is the most popular way to implement retry patterns in .NET Core. It integrates seamlessly with IHttpClientFactory.
Add the necessary Polly packages to your project.
//shell dotnet add package Polly dotnet add package Microsoft.Extensions.Http.Polly
You can define a retry policy and attach it to your HttpClient using IHttpClientFactory in your application's startup. This keeps the retry logic centralized and separate from your business logic.
In this example, the policy retries up to three times with an exponential backoff.
//csharp
using Microsoft.Extensions.Http.Polly;
using Polly;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient("resilientClient")
.AddPolicyHandler(GetRetryPolicy());
var app = builder.Build();
// Other middleware and endpoints...
app.Run();
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
// Define a retry policy that handles transient HTTP errors
// (network issues, 5xx status codes, and 408 Request Timeout).
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound) // Optionally, retry on a 404
.WaitAndRetryAsync(3, // Retry 3 times
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), // Exponential backoff
onRetry: (outcome, timespan, retryCount, context) =>
{
Console.WriteLine($"Request failed with {outcome.Exception?.Message}. Waiting {timespan.TotalSeconds}s before next retry. Retry attempt {retryCount}.");
});
}
Inject IHttpClientFactory into your service or controller. When you create a client with the factory, the configured retry policy is automatically applied.
//csharp
public class MyApiService
{
private readonly HttpClient _httpClient;
public MyApiService(IHttpClientFactory clientFactory)
{
_httpClient = clientFactory.CreateClient("resilientClient");
}
public async Task<string> GetDataAsync()
{
try
{
var response = await _httpClient.GetAsync("https://some-external-api/data");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
// The policy failed after all retries.
Console.WriteLine($"Failed to retrieve data after multiple retries: {ex.Message}");
throw;
}
}
}
While both patterns are used to improve application resilience, they serve different purposes and operate differently.
| π Feature | π Circuit Breaker | π Retry Pattern |
|---|---|---|
| π― Primary Goal | Prevents repeated calls to a failing service, avoiding cascading failures and resource exhaustion. | Handles transient faults by retrying failed operations after a delay. |
| βοΈ Mechanism | Tracks failure rates and opens the circuit to block calls when a threshold is exceeded. Allows recovery via half-open state. | Retries operations a set number of times with optional delay strategies like exponential backoff. |
| π¨ Response to Failure | Blocks calls immediately when in open state, returning a fast failure response. | Retries the operation after delay until success or retry limit is reached. |
| π§© Use Case | Best for persistent failures or unstable services that need time to recover. | Best for temporary issues like network glitches or timeouts. |
| π Integration | Often used with IHttpClientFactory and Polly for HTTP calls. | Also implemented with Polly and IHttpClientFactory for retry logic. |
| β οΈ Risk | May block healthy requests if thresholds are too sensitive. | May cause retry storms or overload services if not throttled. |
| π‘ Best Practice | Combine with fallback and logging. Use separate breakers for different dependencies. | Use exponential backoff with jitter. Apply selectively to transient faults. |
| Circuit Breaker Pattern in .NET | OCR In ASP.NET | |