Поделиться через


Класс System.Net.Http.HttpClient

В этой статье приводятся дополнительные замечания к справочной документации по этому API.

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

Создание экземпляров

HttpClient предназначен для создания экземпляра один раз и повторного использования в течение всей жизни приложения. В .NET Core и .NET 5+httpClient пулы в экземпляре обработчика и повторно используют подключение для нескольких запросов. Если создать экземпляр класса HttpClient для каждого запроса, количество сокетов, доступных при тяжелых нагрузках, будет исчерпано. Это исчерпание приведет к SocketException ошибкам.

Дополнительные параметры можно настроить, передав обработчик, например HttpClientHandler (или SocketsHttpHandler в .NET Core 2.1 или более поздней версии), как часть конструктора. Свойства подключения обработчика нельзя изменить после отправки запроса, поэтому одна из причин создания нового экземпляра HttpClient может быть, если необходимо изменить свойства подключения. Если для разных запросов требуются разные параметры, это также может привести к приложению с несколькими HttpClient экземплярами, где каждый экземпляр настроен соответствующим образом, а затем запросы выдаются на соответствующем клиенте.

HttpClient разрешает только записи DNS при создании подключения. Он не отслеживает срок жизни (TTL), указанный DNS-сервером. Если записи DNS регулярно изменяются, что может произойти в некоторых сценариях контейнеров, клиент не будет уважать эти обновления. Чтобы устранить эту проблему, можно ограничить время существования подключения, задав SocketsHttpHandler.PooledConnectionLifetime свойство, чтобы при замене подключения требуется поиск DNS.

public class GoodController : ApiController
{
    private static readonly HttpClient httpClient;

    static GoodController()
    {
        var socketsHandler = new SocketsHttpHandler
        {
            PooledConnectionLifetime = TimeSpan.FromMinutes(2)
        };

        httpClient = new HttpClient(socketsHandler);
    }
}

В качестве альтернативы созданию только одного экземпляра HttpClient можно также использовать IHttpClientFactory для управления экземплярами HttpClient. Дополнительные сведения см. в руководствах по использованию HttpClient.

Финансовый дериватив

Он HttpClient также выступает в качестве базового класса для более конкретных HTTP-клиентов. Примером будет FacebookHttpClient, предоставляющий дополнительные методы, относящиеся к веб-службе Facebook (например, GetFriends метод). Производные классы не должны переопределять виртуальные методы класса. Вместо этого используйте перегрузку конструктора, которая принимает HttpMessageHandler для настройки любой предварительной или после запроса обработки.

Транспорты

Это HttpClient высокоуровневый API, который упаковывает функциональные возможности нижнего уровня, доступные на каждой платформе, где она выполняется.

На каждой платформе HttpClient пытается использовать лучший доступный транспорт:

Узел или среда выполнения Серверная часть
Windows/платформа .NET Framework HttpWebRequest
Windows/Mono HttpWebRequest
Windows/UWP Windows native WinHttpHandler (поддерживаетСЯ HTTP 2.0)
Windows/.NET Core 1.0-2.0 Windows native WinHttpHandler (поддерживаетСЯ HTTP 2.0)
Android/Xamarin Выбран во время сборки. Можно использовать HttpWebRequest или настраивать для использования собственного устройства Android HttpURLConnection
iOS, tvOS, watchOS/Xamarin Выбран во время сборки. Можно использовать HttpWebRequest или настроить для использования Apple NSUrlSession (с поддержкой HTTP 2.0)
macOS/Xamarin Выбран во время сборки. Можно использовать HttpWebRequest или настроить для использования Apple NSUrlSession (с поддержкой HTTP 2.0)
macOS/Mono HttpWebRequest
macOS/.NET Core 1.0-2.0 libcurlТранспорт HTTP на основе (с поддержкой HTTP 2.0)
Linux/Mono HttpWebRequest
Linux/.NET Core 1.0-2.0 libcurlТранспорт HTTP на основе (с поддержкой HTTP 2.0)
.NET Core 2.1 и более поздних версий System.Net.Http.SocketsHttpHandler

Пользователи также могут настроить определенный транспорт для HttpClient вызова конструктора HttpClient , который принимает HttpMessageHandlerобъект.

платформа .NET Framework & Mono

По умолчанию для платформа .NET Framework и Mono HttpWebRequest используется для отправки запросов на сервер. Это поведение можно изменить, указав другой обработчик в одной из перегрузок конструктора с параметром HttpMessageHandler . Если требуются такие функции, как проверка подлинности или кэширование, можно использовать WebRequestHandler для настройки параметров, а экземпляр можно передать конструктору. Возвращаемый обработчик можно передать в перегрузку конструктора, которая имеет HttpMessageHandler параметр.

.NET Core

Начиная с .NET Core 2.1, System.Net.Http.SocketsHttpHandler класс вместо HttpClientHandler реализации предоставляет реализацию, используемую более высоким уровнем сетевых классов HTTP, таких как HttpClient. Использование SocketsHttpHandler предлагает ряд преимуществ:

  • Значительное улучшение производительности по сравнению с предыдущей реализацией.
  • Устранение зависимостей платформы, упрощающее развертывание и обслуживание. Например, libcurl больше не зависит от .NET Core для macOS и .NET Core для Linux.
  • Согласованное поведение на всех платформах .NET.

Если это изменение нежелательно, в Windows можно продолжать использовать WinHttpHandler , ссылаясь на его пакет NuGet и передав его в конструктор HttpClient вручную.

Настройка поведения с помощью параметров конфигурации среды выполнения

Некоторые аспекты HttpClientповедения настраиваются с помощью параметров конфигурации среды выполнения. Однако поведение этих коммутаторов отличается от версий .NET. Например, в .NET Core 2.1 – 3.1 можно настроить, используется ли SocketsHttpHandler этот параметр по умолчанию, но этот параметр больше недоступен начиная с .NET 5.

Организация пулов соединений

HttpClient пулы HTTP, где это возможно, и использует их для нескольких запросов. Это может иметь значительное преимущество производительности, особенно для HTTPS-запросов, так как подтверждение подключения выполняется только один раз.

свойства пула Подключение можно настроить для объекта HttpClientHandler или SocketsHttpHandler передать во время строительства, в том числе MaxConnectionsPerServer, PooledConnectionIdleTimeoutи PooledConnectionLifetime.

Удаление экземпляра HttpClient закрывает открытые подключения и отменяет все ожидающие запросы.

Примечание.

При одновременной отправке запросов HTTP/1.1 на тот же сервер можно создать новые подключения. Даже если вы повторно используете HttpClient экземпляр, если скорость запросов высока или есть какие-либо ограничения брандмауэра, которые могут исчерпать доступные сокеты из-за таймеров очистки TCP по умолчанию. Чтобы ограничить количество одновременных подключений, можно задать MaxConnectionsPerServer свойство. По умолчанию число одновременных подключений HTTP/1.1 не ограничено.

Время существования буферизации и запроса

По умолчанию методы HttpClient (за исключением GetStreamAsync) буферизуют ответы с сервера, считывая весь текст ответа в память, прежде чем возвращать асинхронный результат. Эти запросы будут продолжаться до тех пор, пока не будет выполнено одно из следующих действий:

  • Успешное Task<TResult> и возвращает результат.
  • Достигнуто Timeout , в этом случае Task<TResult> будет отменено.
  • CancellationToken Выполняется передача в некоторые перегрузки методов.
  • Вызывается метод CancelPendingRequests().
  • HttpClient удаляется.

Поведение буферизации можно изменить на основе каждого запроса с помощью параметра, HttpCompletionOption доступного для некоторых перегрузок методов. Этот аргумент можно использовать для указания того, следует ли Task<TResult> считать его полным после чтения только заголовков ответа или после чтения и буферизации содержимого ответа.

Если приложение, использующее HttpClient и связанные классы в System.Net.Http пространстве имен, намерено скачать большие объемы данных (50 мегабайт или больше), приложение должно передавать эти скачиваемые файлы и не использовать буферизацию по умолчанию. Если вы используете буферизацию по умолчанию, использование памяти клиента будет очень большим, что может привести к значительно снижению производительности.

Потокобезопасность

Следующие методы являются потокобезопасными:

Прокси

По умолчанию HttpClient считывает конфигурацию прокси-сервера из переменных среды или параметров пользователя или системы в зависимости от платформы. Это поведение можно изменить, передав или WebProxyIWebProxy в порядке приоритета:

  • Свойство Proxy httpClientHandler, переданное во время строительства HttpClient
  • Статичное DefaultProxy свойство (влияет на все экземпляры)

Вы можете отключить прокси-сервер с помощью UseProxy. Конфигурация по умолчанию для пользователей Windows заключается в попытке и обнаружении прокси-сервера с помощью обнаружения сети, что может быть медленно. Для приложений с высокой пропускной способностью, где известно, что прокси-сервер не требуется, следует отключить прокси-сервер.

Параметры прокси-сервера (например Credentials), необходимо изменить только перед первым запросом с помощью HttpClient. Изменения, внесенные после первого использования HttpClient, могут не отражаться в последующих запросах.

Время ожидания

Можно задать Timeout время ожидания по умолчанию для всех HTTP-запросов из экземпляра HttpClient. Время ожидания применяется только к методам xxxAsync, которые вызывают инициирование запроса или ответа. Если достигнуто время ожидания, Task<TResult> отменяется запрос.

При создании объекта HttpClient можно задать несколько дополнительных тайм-аутов при передаче экземпляра SocketsHttpHandler :

Свойство Description
ConnectTimeout Указывает время ожидания, используемое при запросе, для создания нового TCP-подключения. Если происходит время ожидания, запрос Task<TResult> отменяется.
PooledConnectionLifetime Указывает время ожидания, используемое для каждого подключения в пуле соединений. Если подключение неактивно, подключение немедленно закрывается; в противном случае соединение закрывается в конце текущего запроса.
PooledConnectionIdleTimeout Если подключение в пуле подключений неактивно в течение этого времени, подключение закрывается.
Expect100ContinueTimeout Если запрос имеет заголовок "Ожидает: 100-continue", он задерживает отправку содержимого до истечения времени ожидания или до получения ответа "100-continue".

HttpClient разрешает только записи DNS при создании подключений. Он не отслеживает срок жизни (TTL), указанный DNS-сервером. Если записи DNS изменяются регулярно, что может произойти в некоторых сценариях контейнеров, можно использовать PooledConnectionLifetime для ограничения времени существования подключения, чтобы при замене подключения требуется поиск DNS.