那么,问题是为什么在 using 块中使用 HttpClient 是错误的,但在 WebApi 上下文中呢?
我一直在读这篇文章不要阻止异步代码 https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html。其中我们有以下示例:
public static async Task<JObject> GetJsonAsync(Uri uri)
{
// (real-world code shouldn't use HttpClient in a using block; this is just example code)
using (var client = new HttpClient())
{
var jsonString = await client.GetStringAsync(uri);
return JObject.Parse(jsonString);
}
}
// My "top-level" method.
public class MyController : ApiController
{
public string Get()
{
var jsonTask = GetJsonAsync(...);
return jsonTask.Result.ToString();
}
}
评论// (real-world code shouldn't use HttpClient in a using block; this is just example code)
刚刚触发了我。我一直都是这样使用HttpClient的。
我检查的下一件事是Microsoft 关于 HttpClient 类的文档 https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=netframework-4.7.2。
在其中,我们有以下声明以及提供的源示例:
HttpClient 旨在实例化一次并在整个过程中重复使用
应用程序的生命周期。实例化 HttpClient 类
每个请求都会耗尽重负载下可用的套接字数量
负载。这将导致 SocketException 错误。下面是一个例子
正确使用 HttpClient。
public class GoodController : ApiController
{
private static readonly HttpClient HttpClient;
static GoodController()
{
HttpClient = new HttpClient();
}
}
那么构造函数不是在每个请求上调用,因此每次都会创建一个新的 HttpClient 吗?
Thanks!
这个问题的答案有点长……
最初,官方建议是使用HttpClient
in a using
堵塞。但是这个造成了大规模的问题 https://www.aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/,基本上用掉了很多连接TIME_WAIT
state.
所以,官方建议改为使用staticHttpClient
。但这引起了问题它永远无法正确处理 DNS 更新 https://github.com/dotnet/runtime/issues/18348.
因此,ASP.NET 团队想出了IHttpClientFactory在 .NET Core 2.1 中 https://www.stevejgordon.co.uk/introduction-to-httpclientfactory-aspnetcore,因此代码(或至少在现代平台上运行的代码)可以重用HttpClient
实例(或者更准确地说,消息处理程序这些情况),避免TIME_WAIT
问题,而且还定期关闭这些连接以避免 DNS 问题。
但与此同时,.NET 团队想出了SocketsHttpHandler也在 .NET Core 2.1 中 https://www.stevejgordon.co.uk/httpclient-connection-pooling-in-dotnet-core, which also进行连接池。
因此,在现代平台上,您可以使用IHttpClientFactory
或静态/单例HttpClient
。在较旧的平台(包括 .NET Framework)上,您将使用静态/单例HttpClient
要么接受 DNS 问题,要么使用其他解决方法 http://byterot.blogspot.com/2016/07/singleton-httpclient-dns.html.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)