Ho sempre utilizzato HttpClient nelle mie applicazioni senza mai approfondire realmente il suo funzionamento interno. Lo consideravo uno strumento semplice e affidabile per effettuare richieste HTTP, fino a quando non ho incontrato il famigerato “socket exhaustion” – una situazione in cui le porte TCP disponibili si esauriscono a causa della creazione eccessiva di connessioni non correttamente gestite.
Il problema si manifesta quando creiamo e dismettiamo istanze di HttpClient troppo frequentemente. Ogni nuova istanza stabilisce nuove connessioni TCP che, nonostante il dispose dell’HttpClient, rimangono in uno stato “TIME_WAIT
” per un periodo significativo (circa 60 secondi in macOS). Con un traffico sostenuto, questo può portare rapidamente all’esaurimento delle porte disponibili (circa 16.384 su macOS), causando errori nelle nuove connessioni.
Le limitazioni di HttpClient
HttpClient è un potente strumento per effettuare richieste HTTP in .NET, ma presenta alcune limitazioni significative che possono sfuggire a chi, come me, non ne ha esplorato a fondo il funzionamento:
Gestione delle connessioni
HttpClient mantiene le connessioni aperte per un periodo prolungato, anche dopo il completamento della richiesta.
Lifecycle management
È comune creare e distruggere istanze di HttpClient per ogni richiesta, causando problemi di performance e potenziali leak di risorse.
DNS changes
HttpClient non gestisce automaticamente i cambiamenti DNS, potendo causare problemi in ambienti di lunga durata.
Cos’è HttpClientFactory
HttpClientFactory è la soluzione proposta da Microsoft per affrontare queste limitazioni. Ecco perché è importante conoscerlo e considerare di utilizzarlo:
Gestione delle connessioni
HttpClientFactory gestisce internamente il pool di connessioni, riducendo il rischio di socket exhaustion.
Lifecycle ottimizzato
Crea e gestisce istanze di HttpClient in modo efficiente, eliminando la necessità di creare nuove istanze per ogni richiesta.
Configurazione centralizzata
Permette di configurare e personalizzare le istanze di HttpClient in un unico punto.
Come Utilizzare HttpClientFactory
Utilizzare HttpClientFactory è sorprendentemente semplice, e una volta che avrai iniziato a integrarlo nei tuoi progetti, ti chiederai perché non l’hai scoperto prima. La sua facilità d’uso, combinata con i potenti benefici che offre, lo rende una scelta eccellente per gestire le richieste HTTP in modo efficiente e sicuro.
// In Startup.cs o Program.cs
services.AddHttpClient("GitHub", client =>
{
client.BaseAddress = new Uri("https://api.github.com");
client.DefaultRequestHeaders.Add("User-Agent", "YourCoolApp");
client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
});
// Nel tuo service o controller
public class GitHubService
{
private readonly IHttpClientFactory _clientFactory;
public GitHubService(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
public async Task<string> GetUserRepos(string username)
{
var client = _clientFactory.CreateClient("GitHub");
var response = await client.GetAsync($"/users/{username}/repos");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
Come puoi vedere, l’implementazione è incredibilmente semplice. Con poche righe di codice, ottieni una gestione ottimizzata delle connessioni HTTP, eviti il rischio di socket exhaustion e benefici di una configurazione centralizzata.
Conclusione
L’adozione di HttpClientFactory non solo risolve i problemi di socket exhaustion e altre limitazioni di HttpClient, ma offre anche un approccio più robusto e scalabile per gestire le richieste HTTP nelle applicazioni .NET.
Una volta che avrai integrato HttpClientFactory nei tuoi progetti, ti chiederai come hai fatto a farne a meno fino ad ora. La sua semplicità d’uso, unita ai potenti benefici che offre, lo rende uno strumento indispensabile per ogni sviluppatore .NET che lavora con richieste HTTP.