Clase System.Net.Http.HttpClient

En este artículo se proporcionan comentarios adicionales a la documentación de referencia de esta API.

La HttpClient instancia de clase actúa como una sesión para enviar solicitudes HTTP. Una HttpClient instancia es una colección de valores aplicados a todas las solicitudes ejecutadas por esa instancia. Además, cada HttpClient instancia usa su propio grupo de conexiones, aislando sus solicitudes de las solicitudes ejecutadas por otras HttpClient instancias.

Creación de instancias

HttpClient está pensado para crear instancias una vez y reutilizarse durante toda la vida útil de una aplicación. En .NET Core y .NET 5+, httpClient agrupa las conexiones dentro de la instancia del controlador y reutiliza una conexión entre varias solicitudes. Si crea una instancia de una clase HttpClient para cada solicitud, se agotará el número de sockets disponibles en cargas pesadas. Este agotamiento provocará SocketException errores.

Puede configurar opciones adicionales pasando un "controlador", como HttpClientHandler (o SocketsHttpHandler en .NET Core 2.1 o posterior), como parte del constructor. Las propiedades de conexión del controlador no se pueden cambiar una vez enviada una solicitud, por lo que un motivo para crear una nueva instancia de HttpClient sería si necesita cambiar las propiedades de conexión. Si las diferentes solicitudes requieren una configuración diferente, esto también puede provocar que una aplicación tenga varias HttpClient instancias, donde cada instancia está configurada correctamente y, a continuación, se emiten solicitudes en el cliente correspondiente.

HttpClient solo resuelve las entradas DNS cuando se crea una conexión. No realiza ningún seguimiento de las duraciones de período de vida (TTL) especificadas por el servidor DNS. Si las entradas DNS cambian con regularidad, lo que puede ocurrir en algunos escenarios de contenedor, el cliente no respetará esas actualizaciones. Para resolver este problema, puede limitar la duración de la conexión mediante la configuración de la propiedad SocketsHttpHandler.PooledConnectionLifetime, de modo que la búsqueda de DNS sea obligatoria cuando se reemplace la conexión.

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

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

        httpClient = new HttpClient(socketsHandler);
    }
}

Como alternativa a crear solo una instancia de HttpClient, también puede usar IHttpClientFactory para administrar las instancias de HttpClient. Para obtener más información, consulte Directrices para usar HttpClient.

Derivación

HttpClient también actúa como una clase base para clientes HTTP más específicos. Un ejemplo sería un FacebookHttpClient que proporciona métodos adicionales específicos de un servicio web de Facebook (por ejemplo, un GetFriends método). Las clases derivadas no deben invalidar los métodos virtuales en la clase . En su lugar, use una sobrecarga de constructor que acepte HttpMessageHandler para configurar cualquier procesamiento previo o posterior a la solicitud.

Transportes

HttpClient es una API de alto nivel que ajusta la funcionalidad de nivel inferior disponible en cada plataforma donde se ejecuta.

En cada plataforma, HttpClient intenta usar el mejor transporte disponible:

Host/Runtime Back-end
Windows/.NET Framework HttpWebRequest
Windows/Mono HttpWebRequest
Windows/UWP Windows nativo WinHttpHandler (compatible con HTTP 2.0)
Windows/.NET Core 1.0-2.0 Windows nativo WinHttpHandler (compatible con HTTP 2.0)
Android/Xamarin Seleccionado en tiempo de compilación. Puede usar HttpWebRequest o configurarse para usar el nativo de Android HttpURLConnection
iOS, tvOS, watchOS/Xamarin Seleccionado en tiempo de compilación. Puede usar HttpWebRequest o configurarse para usar apple NSUrlSession (compatible con HTTP 2.0)
macOS/Xamarin Seleccionado en tiempo de compilación. Puede usar HttpWebRequest o configurarse para usar apple NSUrlSession (compatible con HTTP 2.0)
macOS/Mono HttpWebRequest
macOS/.NET Core 1.0-2.0 libcurlTransporte HTTP basado en (compatible con HTTP 2.0)
Linux/Mono HttpWebRequest
Linux/.NET Core 1.0-2.0 libcurlTransporte HTTP basado en (compatible con HTTP 2.0)
.NET Core 2.1 y versiones posteriores System.Net.Http.SocketsHttpHandler

Los usuarios también pueden configurar un transporte específico para HttpClient mediante la invocación del HttpClient constructor que toma un HttpMessageHandler.

.NET Framework y Mono

De forma predeterminada, en .NET Framework y Mono, HttpWebRequest se usa para enviar solicitudes al servidor. Este comportamiento se puede modificar especificando un controlador diferente en una de las sobrecargas del constructor con un HttpMessageHandler parámetro . Si necesita características como la autenticación o el almacenamiento en caché, puede usar WebRequestHandler para configurar las opciones y la instancia se puede pasar al constructor. El controlador devuelto se puede pasar a una sobrecarga de constructor que tiene un HttpMessageHandler parámetro .

.NET Core

A partir de .NET Core 2.1, la System.Net.Http.SocketsHttpHandler clase en lugar de proporciona la implementación que usan las clases de red HTTP de HttpClientHandler nivel superior, como HttpClient. El uso de SocketsHttpHandler ofrece una serie de ventajas:

  • Una mejora significativa del rendimiento en comparación con la implementación anterior.
  • La eliminación de dependencias de plataforma, lo que simplifica la implementación y el mantenimiento. Por ejemplo, libcurl ya no es una dependencia de .NET Core para macOS y .NET Core para Linux.
  • Comportamiento coherente en todas las plataformas .NET.

Si este cambio no es deseable, en Windows puede seguir usando WinHttpHandler haciendo referencia a su paquete NuGet y pasándolo manualmente al constructor de HttpClient.

Configuración del comportamiento mediante opciones de configuración en tiempo de ejecución

Algunos aspectos del comportamiento de son personalizables a través de las opciones de configuración en tiempo de HttpClientejecución. Sin embargo, el comportamiento de estos modificadores difiere a través de las versiones de .NET. Por ejemplo, en .NET Core 2.1 - 3.1, puede configurar si SocketsHttpHandler se usa de forma predeterminada, pero esa opción ya no está disponible a partir de .NET 5.

Agrupación de conexiones

HttpClient agrupa las conexiones HTTP siempre que sea posible y las usa para más de una solicitud. Esto puede tener una ventaja significativa de rendimiento, especialmente para las solicitudes HTTPS, ya que el protocolo de enlace de conexión solo se realiza una vez.

Conectar las propiedades del grupo de Conectar se pueden configurar en o HttpClientHandlerSocketsHttpHandler pasar durante la construcción, incluidos MaxConnectionsPerServer, PooledConnectionIdleTimeouty PooledConnectionLifetime.

La eliminación de la instancia httpClient cierra las conexiones abiertas y cancela las solicitudes pendientes.

Nota:

Si envía simultáneamente solicitudes HTTP/1.1 al mismo servidor, se pueden crear nuevas conexiones. Aunque reutilice la HttpClient instancia, si la tasa de solicitudes es alta o si hay limitaciones de firewall, puede agotar los sockets disponibles debido a los temporizadores de limpieza de TCP predeterminados. Para limitar el número de conexiones simultáneas, puede establecer la MaxConnectionsPerServer propiedad . De forma predeterminada, el número de conexiones HTTP/1.1 simultáneas es ilimitada.

Almacenamiento en búfer y duración de las solicitudes

De forma predeterminada, los métodos HttpClient (excepto GetStreamAsync) almacenar en búfer las respuestas del servidor, leyendo todo el cuerpo de la respuesta en la memoria antes de devolver el resultado asincrónico. Esas solicitudes continuarán hasta que se produzca una de las siguientes acciones:

Puede cambiar el comportamiento de almacenamiento en búfer por solicitud mediante el HttpCompletionOption parámetro disponible en algunas sobrecargas de método. Este argumento se puede usar para especificar si Task<TResult> se debe considerar completado después de leer solo los encabezados de respuesta, o después de leer y almacenar en búfer el contenido de la respuesta.

Si la aplicación que usa HttpClient y clases relacionadas en el System.Net.Http espacio de nombres pretende descargar grandes cantidades de datos (50 megabytes o más), la aplicación debe transmitir esas descargas y no usar el almacenamiento en búfer predeterminado. Si usa el almacenamiento en búfer predeterminado, el uso de memoria del cliente obtendrá un rendimiento muy grande, lo que podría reducir considerablemente el rendimiento.

Seguridad para subprocesos

Los métodos siguientes son seguros para subprocesos:

Proxies

De forma predeterminada, HttpClient lee la configuración del proxy de las variables de entorno o la configuración del usuario o del sistema, en función de la plataforma. Para cambiar este comportamiento, pase o WebProxyIWebProxy a , en orden de prioridad:

  • La Proxy propiedad de un HttpClientHandler pasado durante la construcción de HttpClient
  • La DefaultProxy propiedad estática (afecta a todas las instancias)

Puede deshabilitar el proxy mediante UseProxy. La configuración predeterminada para los usuarios de Windows es intentar detectar un proxy mediante la detección de red, lo que puede ser lento. Para las aplicaciones de alto rendimiento en las que se sabe que no se requiere un proxy, debe deshabilitar el proxy.

La configuración del proxy (como Credentials) solo debe cambiarse antes de que se realice la primera solicitud mediante HttpClient. Es posible que los cambios realizados después de usar HttpClient por primera vez no se reflejen en las solicitudes posteriores.

Tiempos de espera

Puede usar Timeout para establecer un tiempo de espera predeterminado para todas las solicitudes HTTP de la instancia de HttpClient. El tiempo de espera solo se aplica a los métodos xxxAsync que hacen que se inicie una solicitud o respuesta. Si se alcanza el tiempo de espera, se cancela para Task<TResult> esa solicitud.

Puede establecer algunos tiempos de espera adicionales si pasa una SocketsHttpHandler instancia al construir el objeto HttpClient:

Propiedad Descripción
ConnectTimeout Especifica un tiempo de espera que se usa cuando una solicitud requiere que se cree una nueva conexión TCP. Si se produce el tiempo de espera, se cancela la solicitud Task<TResult> .
PooledConnectionLifetime Especifica un tiempo de espera que se usará para cada conexión del grupo de conexiones. Si la conexión está inactiva, la conexión se cierra inmediatamente; De lo contrario, la conexión se cierra al final de la solicitud actual.
PooledConnectionIdleTimeout Si una conexión del grupo de conexiones está inactiva durante este tiempo, se cierra la conexión.
Expect100ContinueTimeout Si la solicitud tiene un encabezado "Expect: 100-continue", retrasa el envío de contenido hasta el tiempo de espera o hasta que se reciba una respuesta "100-continue".

HttpClient solo resuelve las entradas DNS cuando se crean las conexiones. No realiza ningún seguimiento de las duraciones de período de vida (TTL) especificadas por el servidor DNS. Si las entradas DNS cambian periódicamente, lo que puede ocurrir en algunos escenarios de contenedor, puede usar PooledConnectionLifetime para limitar la duración de la conexión para que se requiera la búsqueda DNS al reemplazar la conexión.