HttpClientFactory for Resilient HTTP Requests
Mind Map Summary
- Topic: HttpClientFactory for Resilient HTTP Requests
- Problems with
new HttpClient()
:- Socket Exhaustion: Creating a new
HttpClient
for each request can exhaust the number of available sockets. - DNS Changes:
HttpClient
does not respect DNS changes, which can cause problems in dynamic environments.
- Socket Exhaustion: Creating a new
HttpClientFactory
:- Manages
HttpClient
instances: Manages the lifetime ofHttpClient
instances to avoid the problems withnew HttpClient()
. - Named and Typed Clients: Allows you to configure named and typed clients with specific settings, such as base address and default headers.
- Integration with Polly: Integrates with Polly to add resilience patterns, such as retry and circuit breaker.
- Manages
- Polly: A .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner.
Practice Exercise
Use HttpClientFactory
to create a typed client for an external API. Use the Polly extension to add a transient error handling policy that retries failed requests (HTTP 5xx or network errors) up to three times with an exponential backoff.
Answer
1. Typed Client:
public class MyApiClient
{
private readonly HttpClient _httpClient;
public MyApiClient(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<string> GetDataAsync()
{
var response = await _httpClient.GetAsync("/data");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
2. Configure HttpClientFactory
and Polly in Program.cs
:
using Polly;
using Polly.Extensions.Http;
builder.Services.AddHttpClient<MyApiClient>(client =>
{
client.BaseAddress = new Uri("https://api.example.com");
})
.AddPolicyHandler(GetRetryPolicy());
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}
Explanation:
- We create a typed client
MyApiClient
that takes anHttpClient
in its constructor. - We use
AddHttpClient<MyApiClient>()
to register the typed client with theHttpClientFactory
. - We use
AddPolicyHandler()
to add a Polly policy to the client. - The policy handles transient HTTP errors (5xx and 408) and retries the request up to three times with an exponential backoff.