我应该缓存和重用从 HttpClientFactory 创建的 HttpClient 吗? [英] Should I cache and reuse HttpClient created from HttpClientFactory?

查看:49
本文介绍了我应该缓存和重用从 HttpClientFactory 创建的 HttpClient 吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们可以在这里阅读您使用的 HTTP 客户端有误,这正在破坏您的稳定软件我们不应该为每个http请求创建和处理HttpClient.相反,它应该被缓存和重用(例如作为 DI 容器中的单例).同样在 HttpClient:

We can read here YOU'RE USING HTTPCLIENT WRONG AND IT IS DESTABILIZING YOUR SOFTWARE that we should not create and dispose HttpClient for each http request. Instead, it should be cached and reused (e.g as Singleton in DI container). As well in official .NET documentation for HttpClient:

HttpClient 旨在实例化一次并在应用程序的整个生命周期中重复使用.为每个请求实例化一个 HttpClient 类将耗尽重负载下可用的套接字数量.这将导致 SocketException 错误.下面是一个正确使用 HttpClient 的例子.

推荐是使用HttpClientFactory,但是看了之后:

The recommendation is to use HttpClientFactory, but after looking at:

  public interface IHttpClientFactory
  {
    /// <summary>
    /// Creates and configures an <see cref="T:System.Net.Http.HttpClient" /> instance using the configuration that corresponds
    /// to the logical name specified by <paramref name="name" />.
    /// </summary>
    /// <param name="name">The logical name of the client to create.</param>
    /// <returns>A new <see cref="T:System.Net.Http.HttpClient" /> instance.</returns>
    /// <remarks>
    /// <para>
    /// Each call to <see cref="M:System.Net.Http.IHttpClientFactory.CreateClient(System.String)" /> is guaranteed to return a new <see cref="T:System.Net.Http.HttpClient" />
    /// instance. Callers may cache the returned <see cref="T:System.Net.Http.HttpClient" /> instance indefinitely or surround
    /// its use in a <langword>using</langword> block to dispose it when desired.
    /// </para>
    /// <para>
    /// The default <see cref="T:System.Net.Http.IHttpClientFactory" /> implementation may cache the underlying
    /// <see cref="T:System.Net.Http.HttpMessageHandler" /> instances to improve performance.
    /// </para>
    /// <para>
    /// Callers are also free to mutate the returned <see cref="T:System.Net.Http.HttpClient" /> instance's public properties
    /// as desired.
    /// </para>
    /// </remarks>
    HttpClient CreateClient(string name);
  }

它表示每次调用都会创建一个 HttpClient 实例并且调用者可以缓存它.

it says that each call will always create a HttpClient instance and caller may cache it.

每次调用 IHttpClientFactory.CreateClient 都保证返回一个新的 HttpClient实例.调用者可以无限期地缓存返回的实例或环绕它在 using 块中使用以在需要时处理它.

那么问题是我应该完全依赖 HttpClientFactory 还是我仍然应该缓存从它创建的 HttpClient?

So question is should I completely rely on HttpClientFactory or I should still cache created HttpClient from it?

在我们的项目中,我们每次发出请求时都使用 HttpClientFactory.CreateClient,但他仍然会遇到套接字异常.

In our project we use HttpClientFactory.CreateClient every time we make request and he will still having socket exceptions.

推荐答案

HttpClient 只是 IDisposable 因为它的 HttpMessageHandlerIDisposable.实际上,HttpMessageHandler 应该是长寿命的.

HttpClient is only IDisposable because its HttpMessageHandler is IDisposable. In reality, it's the HttpMessageHandler which should be long-lived.

HttpClientFactory 通过在内部保持一个长期存在的 HttpMessageHandler 来工作.每当您请求 HttpClient 时,它都会使用长期存在的 HttpMessageHander,并告诉 HttpClient not 进行处理当 HttpClient 被释放时.

HttpClientFactory works by keeping a long-lived HttpMessageHandler internally. Whenever you ask for a HttpClient, it uses the long-lived HttpMessageHander, and tells the HttpClient not to dispose it when the HttpClient is disposed.

你可以看到 :

public HttpClient CreateClient(string name)
{
    // ...

    // Get a cached HttpMessageHandler
    var handler = CreateHandler(name);

    // Give it to a new HttpClient, and tell it not to dispose it
    var client = new HttpClient(handler, disposeHandler: false);

    // ...

    return client;
}

因此,从技术上讲,您是缓存 HttpClient 还是立即处理它并不重要 - 处理它不会做任何事情(因为它被告知不要处理其 HttpClientHandler,因为它由 HttpClientFactory 管理.

So, technically it doesn't matter whether you cache the HttpClient or dispose it straight away - disposing it doesn't do anything (because it's been told not to dispose its HttpClientHandler, as that's managed by the HttpClientFactory).

关于处理 HttpClientMSDN 说:

不需要处理客户端.Disposal 取消传出请求并保证在调用 Dispose 后不能使用给定的 HttpClient 实例.IHttpClientFactory 跟踪和处理 HttpClient 实例使用的资源.HttpClient 实例通常可以被视为不需要处理的 .NET 对象.

Disposal of the client isn't required. Disposal cancels outgoing requests and guarantees the given HttpClient instance can't be used after calling Dispose. IHttpClientFactory tracks and disposes resources used by HttpClient instances. The HttpClient instances can generally be treated as .NET objects not requiring disposal.

保持单个 HttpClient 实例长时间处于活动状态是在 IHttpClientFactory 出现之前使用的常见模式.迁移到 IHttpClientFactory 后,此模式变得不必要.

Keeping a single HttpClient instance alive for a long duration is a common pattern used before the inception of IHttpClientFactory. This pattern becomes unnecessary after migrating to IHttpClientFactory.

我怀疑您看到的 SocketException 有不同的原因.也许问一个关注他们的新问题?

I suspect the SocketExceptions you're seeing have a different cause. Perhaps ask a new question focussed on them?

这篇关于我应该缓存和重用从 HttpClientFactory 创建的 HttpClient 吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆