我相信我们都读过这篇在 2016 年引起轰动的文章:https ://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/
对于那些没有的人,总结一下(强调我的):
您应该在应用程序的整个生命周期内共享一个 HttpClient
HttpClient
实例,而不是为每次执行创建一个新实例。
现在,考虑一个 ASP.NET Core 应用程序,它使用HttpClient
. 它的使用HttpClient
一般分为两种情况:
未经身份验证或使用网站自己的凭据的传出请求 - 在这种情况下
HttpClient
,程序的所有部分都可以共享一个请求。代表网站当前访问者之一发出的传出请求 - 或使用特定于请求的凭据的请求。
- 虽然可以使用单个
HttpClient
实例,但您必须注意不要改变其状态,例如通过设置(例如通过使用扩展方法)。DefaultRequestHeaders
SetBearerToken
- 虽然可以使用单个
几乎所有HttpClient
在 ASP.NET Core 中使用的指南都说:
- 使用类型化客户端(接受
HttpClient
实例作为构造函数参数的 POCO,以及任何其他 DI 服务)。 - 使用 注册这些类型化客户端
services.AddHttpClient<TClient>()
。- 这将注册
TClient
为瞬态实例。 - 这将注册
ITypedHttpClientFactory<TClient>
为瞬态实例。 - 这将注册
IHttpClientFactory
为单例 - 这将注册
IHttpMessageHandlerFactory
为单例
- 这将注册
有了现在讨论的内容,我将把你的注意力引向一个矛盾:
- 著名的博客文章——现在是微软自己的文档——说这些
HttpClient
实例必须是长寿命的。 - ASP.NET Core 的
HttpClient
DI 系统确实确保HttpClient
实例的生命周期很短。
但是,如果博客文章真的应该谈论底层HttpMessageHandler
(这是真正的HttpClient 实现,它只是由薄壳包裹class HttpClient
)而不是外部,这可能class HttpClient
吗?
令人困惑的是,人们也报告了使用长寿命HttpClient
实例的问题,并介绍了其他所有涉及的解决方法,static class ServicePointManager
这让我感到不舒服:
- https://itnext.io/reusing-httpclient-didnt-solve-all-my-problems-142a32a5b4d8
- 作者建议
ServicePointManager
在应用程序启动期间进行调整。 - ...包括禁用 Nagle 的算法 - 我认为这可能是一个非常糟糕的主意。
- 作者建议
- http://byterot.blogspot.com/2016/07/singleton-httpclient-dns.html
- 作者建议使用
ConnectionLeaseTimeout
- ...但是您需要为
ServicePointManager.FindServicePoint()
您调用的每个 URI 调用!这对我来说似乎不对。
- 作者建议使用
我的问题:
HttpClient
实例真的意味着寿命长还是寿命短?- 还是只是
HttpMessageHandler
需要长期存在的实例? - 如果
HttpClient
或HttpMessageHandler
实例意味着长寿:- 如何正确解决
ServicePointManager
两个链接博客文章中提出的问题? - 我是否绝对必须避免使用
HttpClient.DefaultRequestHeaders
,而是明确设置每个Authorization
(Cookies or Credentials) 标头HttpRequestMessage
?有没有其他更省事的方法? - 我可以使用我自己的添加这些标题
DelegatingHandler
吗?那么这个提议的处理程序的 DI 注册应该是什么?
- 如何正确解决
如果
HttpClient
实例(但不是HttpMessageHandler
实例)意味着寿命短:- ...那么可以使用
HttpClient.DefaultRequestHeaders
(andSetBearerToken()
) 吗? HttpMessageHandler
那么实例的生命周期策略是什么?- 我还能使用
HttpClient.DefaultRequestHeaders
(andSetBearerToken()
) 吗?
- ...那么可以使用
如果
HttpClient
实例和HttpMessageHandler
实例的生命周期很短:- 那么 2016 年原始博客文章中提到的问题呢?
- 是否
IHttpClientFactory
采取任何措施来缓解这些问题?
- 是否
- 那么 2016 年原始博客文章中提到的问题呢?