HttpClient được thiết kế để dùng lại. Tạo mới rồi dispose theo từng request gây hai vấn đề đối nghịch nhau:
- Socket exhaustion: dispose không giải phóng socket ngay, kết nối nằm ở trạng thái
TIME_WAITvài phút. Tải cao thì cạn cổng khả dụng của OS, biểu hiện làSocketExceptiondù service đích vẫn khoẻ. - Nhưng nếu chuyển sang một static
HttpClientsống mãi thì gặp lỗi ngược: client chỉ resolve DNS lúc mở kết nối và không tôn trọng TTL, nên khi backend đổi IP (thường gặp khi deploy blue/green, load balancer đổi node) nó vẫn gọi vào IP cũ.
IHttpClientFactory quản lý vòng đời của HttpMessageHandler: pool và tái sử dụng handler, đồng thời xoay vòng theo HandlerLifetime (mặc định 2 phút) nên giải quyết cả hai. Kèm theo đó là cấu hình tập trung và chỗ để gắn DelegatingHandler (retry, auth header, logging).
csharp
builder.Services.AddHttpClient<PaymentClient>(c =>
{
c.BaseAddress = new Uri("https://api.partner.vn/");
c.Timeout = TimeSpan.FromSeconds(10);
});
public class PaymentClient(HttpClient http) { /* injected, do not dispose */ }Giải pháp thay thế nếu không muốn dùng factory: một HttpClient singleton với SocketsHttpHandler { PooledConnectionLifetime = TimeSpan.FromMinutes(2) }.