6

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

似乎最佳实践的普遍共识是通过 Startup.cs->ConfigureServices 方法中的 DI 注册设置 HTTPClient 的 Singleton 实例,以提高性能并避免在我新建 dispose 时可能发生的套接字错误通过 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 类的 ConnectionLeaseTimeout 值,将其设置为更短的值,这将强制关闭连接以刷新 DNS。这篇博文甚至谈到了 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 语句并在每次使用时更新客户端并遭受性能损失?

似乎必须有一个可靠且高性能的解决方案来满足这一常见需求。

4

3 回答 3

9

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

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

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

于 2018-01-03T03:39:36.027 回答
3

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

建议是每个应用程序生命周期只有一个实例,但实际上,当您谈论 Web 应用程序时,应该仅限于请求生命周期。当文档警告要为每个请求更新 anHttpClient时,它是在谈论通过 HttpClient发出的每个请求,而不是您的 Web 应用程序所服务的每个恰好正在使用的请求HttpClient

总而言之,是的,您应该避免using使用HttpClient,但是拥有一个请求范围的实例就可以了。换句话说,它不需要是单例。

于 2018-01-02T19:25:45.713 回答
1

从 2.1 开始,一个不错的选择是使用IHttpClientFactory.

微软文档| 公告博文

于 2018-07-27T15:13:29.447 回答