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 

他展示了问题,但他的结论并没有展示完整正确的最终解决方案。

请注意 - 我问的是 .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、日志记录、类型化的客户端等)以删除所有外部依赖项。