HttpClient 和套接字耗尽 - 澄清?

Roy*_*mir 5 .net c# httpclient .net-4.6.1

这篇文章说我们应该使用静态HttpClient来重用套接字。

但是那里的第一条评论说存在 DNS 更改识别问题,解决方案在此处的另一篇文章中:

第二篇文章建议:

var client = new HttpClient();
client.DefaultRequestHeaders.ConnectionClose = true; 
Run Code Online (Sandbox Code Playgroud)

哪个控制KeepAlive标题。但是会阻止您利用重用套接字的好处

另一个解决方案是:

var sp = ServicePointManager.FindServicePoint(new Uri("http://foo.bar/baz/123?a=ab"));
sp.ConnectionLeaseTimeout = 60*1000; // 1 minute
Run Code Online (Sandbox Code Playgroud)

但:

他没有说是new Httpclient每次我们想发出请求时都应该使用,还是应该仍然使用静态的。

题:

说我想使用这个解决方案:

var sp = ServicePointManager.FindServicePoint(new Uri("http://foo.bar/baz/123?a=ab"));
sp.ConnectionLeaseTimeout = 60*1000; // 1 minute 
Run Code Online (Sandbox Code Playgroud)
  • 我还应该使用这种static HttpClient方法吗?还是new HttpClient每次我想打电话时都应该?或者 - 我应该new HttpClient为每个创建静态/非静态scheme://basedns吗?

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

请注意 - 我问的是 .net 框架。不是 .net 核心。

Pan*_*vos 7

That's a very old article that does explain why HttpClient should be reused, but doesn't explain how to handle DNS changes. That's explained in Singleton HttpClient? Beware of this serious behaviour and how to fix it. That still only deals with one connection.

The obvious answer is to avoid singleton HttpClients but still reuse them for some time. Besides, different sockets are used to connect to different servers, which means we'd really need to reuse (and recycle) sockets per server. The solution came later in the form of HttpClientFactory.

The nice thing is that HttpClientFactory is a .NET Standard 2.0 package, Microsoft.Extensions.Httpthat can be used by both .NET Core and .NET Old, not just ASP.NET Core applications. I use it in console applications for example.

A very good introduction is HttpClientFactory in ASP.NET Core 2.1 (PART 1) by Steve Gordon, and all his articles in that series.

In short, each time we want an HttpClient we ask the factory for an instance :

[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);
    }
}
Run Code Online (Sandbox Code Playgroud)

HttpClient delegates work to a SocketClientHandler. That's what needs to be reused. HttpClientFactory produces HttpClient instances that resuse Socket handlers from a pool of socket handlers. The handlers are recyclec periodically to take care of DNS changes.

更好的是,HttpClientFactory可以与 Polly 结合,为 HttpClient 实例添加重试逻辑。它通过配置处理程序在幕后完成此操作。