Tìm hiểu về HttpClient trong ASP.NET Core

5 min read

http-client-in-net

HttpClient là một trong những lớp phổ biến trong .NET được dùng để gửi HTTP requests và nhận HTTP response từ một resource được xác định bởi một URI. Đây là một phần thiết yếu khi xây dựng các ứng dụng web hoặc microservices cần giao tiếp với các web service khác hoặc API bên ngoài.

Trong bài viết này, chúng ta sẽ khám phá cách sử dụng HttpClient trong một ứng dụng ASP.NET Core, đưa ra các best practice và các sai lầm thường gặp.

HttpClient là gì

HttpClient là một class nằm trong namespace System.Net.Http, nó được dùng để tạo các HTTP request như GET, POST, PUT, DELETE, … . Trong một ứng dụng ASP.NET Core, bạn có thể dùng HttpClient để giao tiếp với các services hoặc APIs bên ngoài, bất kể chúng có base là RESTful hay SOAP.

Trong các phiên bản trước đây của .NET, việc khởi tạo một instance của lớp HttpClient mỗi lần gửi một HTTP request là điều thường thấy. Tuy nhiên, việc này có thể dẫn tới vấn đề về hiệu năng, đặc biệt là khi socket cạn kiệt. Vì vậy, điều quan trọng là phải xử lý HttpClient đúng cách trong các ứng dụng hiện đại.

Cách sử dụng HttpClient trong ASP.NET Core

Trong một ứng dụng ASP.NET Core, ta nên tránh việc khởi tạo trực tiếp HttpClient nhiều lần. Thay vào đó, dùng DI để quản lý lifecycle của nó. Điều này đảm bảo việc tái sử dụng HttpClient xuyên suốt nhiều requests vào không dẫn tới các vấn đề liên quan đến việc quá tải kết nối.

Đăng ký HttpClient vào DI

ASP.NET Core cung cấp hỗ trợ sẵn có cho HttpClient thông qua IHttpClientFactory, được khuyến nghị để quản lý các instance của lớp HttpClient.

Sau đây là cách đăng ký và sử dụng HttpClient trong ứng dụng của bạn:

  1. Đăng ký IHttpClientFactory trong phần cấu hình các services
    Thêm đoạn code sau để đăng ký IHttpClientFactor. Điều này cho phép bạn inject một thể hiện của IHttpClientFactory khi cần trong ứng dụng của bạn.
    services.AddHttpClient();
  2. Inject và sử dụng HttpClient
    Trong các class services hoặc controllers, bạn có thể inject IHttpClientFactory và tạo ra các thể hiện của lớp HttpClient.
    public class MyService
    {
    private readonly IHttpClientFactory _httpClientFactory;

    public MyService(IHttpClientFactory httpClientFactory)
    {
    _httpClientFactory = httpClientFactory;
    }

    public async Task<string> GetDataFromApiAsync()
    {
    var client = _httpClientFactory.CreateClient(); // Get HttpClient instance
    var response = await client.GetAsync("https://api.example.com/data");
    response.EnsureSuccessStatusCode(); // Throws exception if not successful
    return await response.Content.ReadAsStringAsync();
    }
    }
    Trong ví dụ trên, method CreateClient() cung cấp một HttpClient có thể được tái sử dụng, có cấu hình mặc định.

Best practice khi sử dụng HttpClient

Tái sử dụng các thể hiện HttpClient

Như đã đề cập trước đó, việc tái sử dụng các thể hiện HttpClient là rất quan trọng để tránh tình trạng cạn kiệt socket. Bằng cách sử dụng IHttpClientFactory, ASP.NET Core quản lý việc tái sử dụng các kết nối HTTP một cách hiệu quả.

Tránh việc call đồng bộ

Khi gửi request, nên ưu tiên sử dụng các api bất đồng bộ như GetAsync(), PostAsync(),… thay vì các phương thức đồng bộ (như Get() hoặc Post()). Việc gọi các hàm blocking có thể làm giảm hiệu suất nghiêm trọng, đặc biệt là khi có tải lớn.

var result = await client.GetStringAsync("https://api.example.com");

Đặt giá trị timeout và xử lý ngoại lệ

Hãy đảm bảo bạn đã đặt một thời gian timeout phù hợp cho các HTTP request. HttpClient sẽ ném ra ngoại lệ nếu request timeout. bạn có thể cấu hình timeout như sau:

services.AddHttpClient("MyApiClient", client =>
{
    client.Timeout = TimeSpan.FromSeconds(30);  // Set timeout to 30 seconds
});

Thêm vào đó, luôn xử lý các ngoại lệ có thể xảy ra trong quá trình gửi HTTP request. Nhưng ngoại lệ thường gặp bao gồm HttpRequestException (vd: lỗi network) và TaskCanceledException (vd: timeout).

Cấu hình HttpClient với custom headers hoặc Authentication

Bạn có thể cấu hình HttpClient để set các headers mặc định, auth token… Điều này hữu ích cho các API yêu cầu các headers tùy chỉnh, chẳng hạn như token OAuth:

services.AddHttpClient("MyApiClient", client =>
{
    client.DefaultRequestHeaders.Add("Authorization", "Bearer your_token_here");
});

Sử dụng named / typed HttpClient

Nếu bạn đang gọi các API bên ngoài khác nhau, hãy cân nhắc sử dụng named (được định danh bằng tên) hoặc typed (định nghĩa trước kiểu) clients để khiến cho code clean hơn và dễ bảo trì.

  • Named clients: Đặt một định danh cho một client cụ thể và dùng nó khi cần:
services.AddHttpClient("MyNamedClient", client =>
{
    client.BaseAddress = new Uri("https://api.example.com");
});
  • Typed clients: tạo một lớp cụ thể bao bọc HttpClient để có thể sử dụng các logic phức tạp hơn
public class MyApiClient
{
    private readonly HttpClient _client;

    public MyApiClient(HttpClient client)
    {
        _client = client;
    }

    public async Task<string> GetSomeDataAsync()
    {
        var response = await _client.GetAsync("endpoint");
        return await response.Content.ReadAsStringAsync();
    }
}

Đăng ký lớp này trong DI:

services.AddHttpClient<MyApiClient>(client =>
{
    client.BaseAddress = new Uri("https://api.example.com");
});

Các lỗi sai thường gặp

  • Không tái sử dụng HttpClient: Việc tạo một thể hiện HttpClient mới mỗi lần có thể dẫn đến tình trạng cạn kiệt socket. Hãy luôn tái sử dụng các thể hiện HttpClient thông qua DI (Dependency Injection) hoặc IHttpClientFactory.
  • Chặn trong mã bất đồng bộ: Không sử dụng Task.Wait() hoặc Result trong mã bất đồng bộ. Điều này có thể dẫn đến deadlock và các nút thắt hiệu suất, đặc biệt là trong việc xử lý yêu cầu/phản hồi đồng bộ của ASP.NET Core.
  • Không thiết lập thời gian chờ (Timeout): Luôn luôn thiết lập thời gian chờ, đặc biệt khi tương tác với các dịch vụ bên ngoài. Nếu không có thời gian chờ, các yêu cầu có thể bị treo vô thời hạn.

Kết luận

HttpClient là một công cụ mạnh mẽ để thực hiện các HTTP request trong ASP.NET Core, nhưng việc sử dụng đúng cách là rất quan trọng để đảm bảo hiệu suất và độ tin cậy. Bằng cách tận dụng dịch vụ IHttpClientFactory, bạn đảm bảo rằng các kết nối HTTP của mình được tái sử dụng, giảm thiểu chi phí và ngăn ngừa các vấn đề như cạn kiệt socket. Việc tuân thủ các phương pháp tốt như thiết lập thời gian chờ, xử lý ngoại lệ và sử dụng các phương thức bất đồng bộ sẽ giúp đảm bảo ứng dụng của bạn luôn phản hồi nhanh và hiệu quả.

Bằng cách áp dụng các mô hình này, ứng dụng của bạn có thể tương tác mượt mà với các API bên ngoài trong khi duy trì hiệu suất và khả năng mở rộng cao.

Tham khảo

https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient
https://learn.microsoft.com/en-us/dotnet/fundamentals/networking/http/httpclient-guidelines

Avatar photo

BigQuery vs Google Cloud SQL – P2

Ở bài viết trước tôi đã tổng quan về khái niệm, các tính năng chính và so sánh sự khác biệt chính của GCP...
Avatar photo Toai Nguyen Cong
11 min read

BigQuery vs Google Cloud SQL – P1

Trong bối cảnh điện toán đám mây không ngừng phát triển, các doanh nghiệp bị ngập trong các lựa chọn khi nói đến việc...
Avatar photo Toai Nguyen Cong
5 min read

Leave a Reply

Your email address will not be published. Required fields are marked *