我应该如何在 ASP.NET Core 2.0 API 中使用 HttpClient

How should I use the HttpClient in an ASP.NET Core 2.0 API

我正在开发 ASP.NET Core 2.0 API,我的 API 需要调用另一个第三方 REST API 来上传和检索文件并获取文件列表和状态信息。我将在 Azure 中托管 API 并计划在暂存和生产槽之间进行蓝绿部署。

似乎最佳实践的普遍共识是在 Startup.cs-->ConfigureSerrvices 方法中通过 DI 注册设置 HTTPClient 的 Singleton 实例,以提高性能并避免可能导致的套接字错误如果我通过 Using 语句新建一个处理每次使用的 HTTPClient 连接,就会发生这种情况。这在以下链接中有说明;

https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.110).aspx#Anchor_5

http://www.nimaara.com/2016/11/01/beware-of-the-net-httpclient/

但是如果我这样做,那么当我在 Azure 中进行蓝绿部署时,我可能会遇到单例实例看不到任何 DNS 更改的问题。这在以下链接中有说明;

http://byterot.blogspot.co.uk/2016/07/singleton-httpclient-dns.html

https://github.com/dotnet/corefx/issues/11224

http://www.nimaara.com/2016/11/01/beware-of-the-net-httpclient/

所以..现在的普遍共识是使用静态 HTTPClient 实例,但控制 ServicePoint class 的 ConnectionLeaseTimeout 值以将其设置为较短的值,这将强制关闭连接以获取刷新的 DNS。 This 博客 post 甚至在 nuget 包(Easy.Common by Nima)中讨论了一个很好的 RestClient 组件,它正确地解决了 ConnectionLeaseTimeout 以及缓存的 DNS 值。

但是,ASP.NET Core 2.0 似乎并未完全实现 ServicePoint,因此目前 ASP.Net Core 2.0 并不真正支持这种方法。

任何人都可以告诉我在 Azure 上的 ASP.NET Core 2.0 API 运行 中使用 HttpClient 的正确方法吗?我希望能够进行蓝绿部署。那么,我是否应该只求助于 Using 语句并在每次使用时都更新客户端并遭受性能损失?

似乎必须有一个可靠且高效的解决方案来满足这一普遍需求。

文档令人困惑,相关文章声称您应该只拥有一个 HttpClient 实例也具有误导性(或被误导,具体取决于视角)。

建议每个应用程序生命周期只有一个实例,但实际上,当您谈论 Web 应用程序时,应该将其限制在 请求生命周期 中。当文档警告为每个请求更新 HttpClient 时,它指的是通过 via HttpClientnot[=26] 发出的每个请求=] 您的 Web 应用程序提供的每个请求恰好使用了 HttpClient.

长话短说,是的,你应该避免 usingHttpClient,但是有一个 request-scoped 实例就好了。也就是说,不需要是单例。

您链接到的某些文章的问题在于,它们导致人们普遍认为设置 ConnectionLeaseTimeout 会在套接字层中执行某种黑魔法,如果你在一个不支持它的平台上,你被搞砸了。这些文章没有触及设置 的实际作用 ,这是一种损害,即定期向被调用的服务器发送 Connection: Close header。就是这样。我已经从源头上验证了这一点,而且非常容易复制。事实上,我已经在我的 Flurl 库中自己完成了,实现细节 here and here.

也就是说,我个人认为 DNS 问题有点夸大了。请注意,例如,连接会在闲置一段时间(默认为 100 秒)后自动关闭。使用 HttpClient 作为单例的好处远远大于风险。

我的建议是每个被调用的第 3 方服务使用一个 实例 。这里的想法是您获得最大程度的重用,同时仍然利用 DefaultRequestHeaders 之类的东西,这些东西往往特定于一项服务。如果您只调用一项服务,那只是一个单例。 (相反,如果您要调用 1000 个不同的服务,您无法以任何方式避免 1000 个打开的套接字。)如果您不希望连接长时间闲置并且想要防御可能的 DNS 切换使用第 3 方服务,定期发送 Connection: close header,或简单地处理并重新创建 HttpClient。请注意,这是一个 trade-off,不是一个完美的解决方案,应该有助于缓解这个问题。

从 2.1 开始,一个好的选择是使用 IHttpClientFactory

Microsoft Docs | Announcement blog post