Работали ли вы с HttpClient в .NET?

Ответ

Да, интенсивно использовал HttpClient. Ключевой момент — правильное управление его жизненным циклом для предотвращения проблем с производительностью, таких как исчерпание сокетов.

Рекомендуемый подход: использовать IHttpClientFactory.

Почему это важно? Прямое создание и удаление HttpClient в using блоке для каждого запроса может привести к задержкам в освобождении сетевых ресурсов. Фабрика управляет пулом HttpMessageHandler, что решает эту проблему.

Пример настройки и использования через DI:

  1. Регистрация в Startup.cs / Program.cs:

    // Базовая регистрация
    builder.Services.AddHttpClient();
    // Именованный клиент с конфигурацией
    builder.Services.AddHttpClient("GitHub", client =>
    {
        client.BaseAddress = new Uri("https://api.github.com/");
        client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
        client.Timeout = TimeSpan.FromSeconds(15);
    });
  2. Использование в сервисе:

    public class DataService : IDataService
    {
        private readonly HttpClient _httpClient;
        // Инжектируем фабрику
        public DataService(IHttpClientFactory httpClientFactory)
        {
            // Создаем клиент. Его не нужно диспозить.
            _httpClient = httpClientFactory.CreateClient("GitHub");
        }
    
        public async Task<User> GetUserAsync(string username)
        {
            var response = await _httpClient.GetAsync($"users/{username}");
            response.EnsureSuccessStatusCode();
            var json = await response.Content.ReadAsStringAsync();
            return JsonSerializer.Deserialize<User>(json);
        }
    }

Дополнительные практики:

  • Использование Polly через AddHttpClient для реализации политик повторных попыток и обработки сбоев.
  • Всегда использовать асинхронные методы (GetAsync, PostAsync).
  • Валидация и обработка ответов (проверка IsSuccessStatusCode или вызов EnsureSuccessStatusCode()).

Ответ 18+ 🔞

Ага, значит, ты с HttpClient на короткой ноге был, да? Ну, это ж классика, блядь. Все через это проходят. Главная засада — если его как попало юзать, он тебе сокеты все в ноль выжрет, и потом сиди, гадай, почему сервис в асфальт влип.

Что делать, чтобы не облажаться? Юзать IHttpClientFactory. Без вариантов.

А почему, спрашивается? Потому что если ты каждый раз в using его пихаешь и думаешь, что молодец, то на деле получается, что сокеты-то не сразу освобождаются, висят как проклятые. Фабрика же умная — она пул этих самых HttpMessageHandler грамотно держит, и проблем не возникает. Просто красота, ёпта.

Вот как это в деле выглядит, смотри:

  1. Прописываем в стартапе (Startup.cs или Program.cs):

    // Самый простой способ — добавил и забыл
    builder.Services.AddHttpClient();
    // А можно и именованного клиента настроить, чтоб не париться потом
    builder.Services.AddHttpClient("GitHub", client =>
    {
        client.BaseAddress = new Uri("https://api.github.com/");
        client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
        client.Timeout = TimeSpan.FromSeconds(15); // Чтобы не ждать до второго пришествия
    });
  2. А вот как этим в сервисе пользоваться:

    public class DataService : IDataService
    {
        private readonly HttpClient _httpClient;
        // Просто просим фабрику, она нам всё даст
        public DataService(IHttpClientFactory httpClientFactory)
        {
            // Берём клиента. И НЕ ДИСПОЗИМ ЕГО, запомни! Фабрика сама всё разрулит.
            _httpClient = httpClientFactory.CreateClient("GitHub");
        }
    
        public async Task<User> GetUserAsync(string username)
        {
            var response = await _httpClient.GetAsync($"users/{username}");
            response.EnsureSuccessStatusCode(); // На всякий пожарный, чтоб не проёбывать ошибки
            var json = await response.Content.ReadAsStringAsync();
            return JsonSerializer.Deserialize<User>(json);
        }
    }

И ещё пару советов на дорожку, а то мало ли:

  • Через AddHttpClient можно Polly прикрутить — для повторных попыток и отказоустойчивости. Очень полезная штука, когда сеть глючит.
  • Только асинхронные методы, блядь, GetAsync, PostAsync. Не надо тут синхронных вызовов, это же 2024 год на дворе.
  • Всегда смотри, что тебе в ответ пришло. Либо IsSuccessStatusCode проверь, либо EnsureSuccessStatusCode() кинь, чтобы не гадать, почему данные не пришли, а сервис уже в нокауте.