HttpClient 和套接字耗尽 - 澄清?
HttpClient and socket exhaustion - clarification?
This article 说我们应该使用静态 HttpClient
以便重用套接字。
但是那里第一条评论说是DNS更改识别问题,解决方案在另一篇文章here:
第二条建议:
var client = new HttpClient();
client.DefaultRequestHeaders.ConnectionClose = true;
控制 KeepAlive
header。
但是会阻止您利用 re-using 套接字
的好处
另一个解决方案是:
var sp = ServicePointManager.FindServicePoint(new Uri("http://foo.bar/baz/123?a=ab"));
sp.ConnectionLeaseTimeout = 60*1000; // 1 minute
但是:
他没说我们是每次请求都用new Httpclient
,还是还是用静态的
问题:
说我想使用这个解决方案:
var sp = ServicePointManager.FindServicePoint(new Uri("http://foo.bar/baz/123?a=ab"));
sp.ConnectionLeaseTimeout = 60*1000; // 1 minute
- 我还应该使用
static HttpClient
方法吗?或者每次我想打电话时都应该new HttpClient
?
或者 - 我应该为每个 scheme://basedns
创建 static/not static new HttpClient
吗?
他展示了问题,但他的结论并没有展示完整正确的最终解决方案。
请注意 - 我问的是 .net 框架。不是 .net 核心。
ServicePointManager
在我看来是片状的,只在 Windows 机器上有效。如果您从 dotnet framework
转到 dotnet core
,实际上是死代码。我不会依赖它来实现我的实现。
我的建议是创建一个仅服务于 HttpClient
.
的一个实例的单例服务
如果您正在使用 asp.net core
,他们会为您提供静态客户端的实现,并在 document
中重新描述问题
那是一篇非常 的老文章,它确实解释了为什么 HttpClient 应该被重用,但没有解释如何处理 DNS 更改。 Singleton HttpClient? Beware of this serious behaviour and how to fix it 中对此进行了解释。那仍然只处理一个连接。
显而易见的答案是避免单例 HttpClients 但仍会重复使用它们一段时间。此外,不同的套接字用于连接到不同的服务器,这意味着我们确实需要重用(和回收)每个服务器的套接字。
解决方案后来以 HttpClientFactory 的形式出现。
好消息是 HttpClientFactory 是一个 .NET Standard 2.0 包,Microsoft.Extensions.Http .NET Core 和 .NET Old 都可以使用,而不仅仅是 ASP.NET Core 应用程序。例如,我在控制台应用程序中使用它。
一个很好的介绍是HttpClientFactory in ASP.NET Core 2.1 (PART 1) by Steve Gordon, and all his articles in that series。
简而言之,每次我们想要一个 HttpClient 时,我们都会向工厂请求一个实例:
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly IHttpClientFactory _httpClientFactory;
public ValuesController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
[HttpGet]
public async Task<ActionResult> Get()
{
var client = _httpClientFactory.CreateClient();
var result = await client.GetStringAsync("http://www.google.com");
return Ok(result);
}
}
HttpClient 将工作委托给 SocketClientHandler。这就是需要重用的东西。 HttpClientFactory 生成重用套接字处理程序池中的套接字处理程序的 HttpClient 实例。处理程序会定期回收以处理 DNS 更改。
更好的是,HttpClientFactory can be combined with Polly 将重试逻辑添加到 HttpClient 实例。它通过配置处理程序在幕后执行此操作。
我自己还没有使用过它,但我认为您可能正在寻找类似的东西:HttpClientFactoryLite。它分叉 Microsoft.Extensions.HttpClientFactory 然后删除所有“自以为是”的部分(例如,DI、日志记录、类型化的客户端等)以删除所有外部依赖项。
This article 说我们应该使用静态 HttpClient
以便重用套接字。
但是那里第一条评论说是DNS更改识别问题,解决方案在另一篇文章here:
第二条建议:
var client = new HttpClient();
client.DefaultRequestHeaders.ConnectionClose = true;
控制 KeepAlive
header。
但是会阻止您利用 re-using 套接字
另一个解决方案是:
var sp = ServicePointManager.FindServicePoint(new Uri("http://foo.bar/baz/123?a=ab"));
sp.ConnectionLeaseTimeout = 60*1000; // 1 minute
但是:
他没说我们是每次请求都用new Httpclient
,还是还是用静态的
问题:
说我想使用这个解决方案:
var sp = ServicePointManager.FindServicePoint(new Uri("http://foo.bar/baz/123?a=ab"));
sp.ConnectionLeaseTimeout = 60*1000; // 1 minute
- 我还应该使用
static HttpClient
方法吗?或者每次我想打电话时都应该new HttpClient
? 或者 - 我应该为每个scheme://basedns
创建 static/not staticnew HttpClient
吗?
他展示了问题,但他的结论并没有展示完整正确的最终解决方案。
请注意 - 我问的是 .net 框架。不是 .net 核心。
ServicePointManager
在我看来是片状的,只在 Windows 机器上有效。如果您从 dotnet framework
转到 dotnet core
,实际上是死代码。我不会依赖它来实现我的实现。
我的建议是创建一个仅服务于 HttpClient
.
如果您正在使用 asp.net core
,他们会为您提供静态客户端的实现,并在 document
那是一篇非常 的老文章,它确实解释了为什么 HttpClient 应该被重用,但没有解释如何处理 DNS 更改。 Singleton HttpClient? Beware of this serious behaviour and how to fix it 中对此进行了解释。那仍然只处理一个连接。
显而易见的答案是避免单例 HttpClients 但仍会重复使用它们一段时间。此外,不同的套接字用于连接到不同的服务器,这意味着我们确实需要重用(和回收)每个服务器的套接字。 解决方案后来以 HttpClientFactory 的形式出现。
好消息是 HttpClientFactory 是一个 .NET Standard 2.0 包,Microsoft.Extensions.Http .NET Core 和 .NET Old 都可以使用,而不仅仅是 ASP.NET Core 应用程序。例如,我在控制台应用程序中使用它。
一个很好的介绍是HttpClientFactory in ASP.NET Core 2.1 (PART 1) by Steve Gordon, and all his articles in that series。
简而言之,每次我们想要一个 HttpClient 时,我们都会向工厂请求一个实例:
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly IHttpClientFactory _httpClientFactory;
public ValuesController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
[HttpGet]
public async Task<ActionResult> Get()
{
var client = _httpClientFactory.CreateClient();
var result = await client.GetStringAsync("http://www.google.com");
return Ok(result);
}
}
HttpClient 将工作委托给 SocketClientHandler。这就是需要重用的东西。 HttpClientFactory 生成重用套接字处理程序池中的套接字处理程序的 HttpClient 实例。处理程序会定期回收以处理 DNS 更改。
更好的是,HttpClientFactory can be combined with Polly 将重试逻辑添加到 HttpClient 实例。它通过配置处理程序在幕后执行此操作。
我自己还没有使用过它,但我认为您可能正在寻找类似的东西:HttpClientFactoryLite。它分叉 Microsoft.Extensions.HttpClientFactory 然后删除所有“自以为是”的部分(例如,DI、日志记录、类型化的客户端等)以删除所有外部依赖项。