如何使用 HttpClient 改善慢速 DNS?

How to improve slow DNS with HttpClient?

我有一个针对特定域的请求需要很长时间才能完成:平均 22 秒。请求本身并没有return很多数据。

var httpClient = new HttpClient();  //instantiated at app start and reused 
var request = new HttpRequestMessage(HttpMethod.Get, "http://www.somedomain.com");
var result = await httpClient.SendAsync(request); //take a really long time

调试了一下,好像跟DNS有关。如果我 运行 完全相同的请求但用 IP 替换域名,它很快(< 200 毫秒)。

如果我使用相同的 HttpClient 实例第二次 运行 请求,它也很快。但是,如果我 运行 在超过一分钟后发出第二个请求,它又变慢了(可能是因为连接在 1 分钟后自动关闭)。

有什么办法可以改善吗? (例如:确保已解析的 DNS 条目会在缓存中保留很长时间)。另外,为什么使用 HttpClient 时该域的 DNS 速度如此之慢?如果我尝试使用 Chrome 访问该域,它会非常快(即使在刷新 DNS 和清除缓存之后)。使用在线服务对该域进行 DNS 查找也非常快。报告的 TTL 为 60 分钟。


编辑:我尝试增加 ServicePointManager.DnsRefreshTimeout(默认设置为 2 分钟)。但这并没有帮助。

调用 Dns.GetHostEntry("somedomain.com") 是即时的并且 return 正确的 IP。我不知道为什么 HttpClient 的请求这么慢。

这不仅仅是关于缓存 DNS 查询。如果您为每个请求创建新的客户端,那么在每个请求之前都会进行 TCP 和 HTTP 握手——这会使您的单个请求变慢。这可能是使用“旧”代理的后续请求更快的原因——握手仅在第一次请求之前进行,但不会在第二次请求之前进行。

我发现问题所在:速度慢的域在 DNS 记录中有一个 IPV6 地址。 这可以通过调用这个函数来确认:

Dns.GetHostEntry("somedomain.com")

首先它会尝试使用 IPV6 进行连接。最终,超时发生。然后它尝试 IPV4(并且有效)。这解释了为什么它这么慢。目前我找到的解决方案是通过自己解析域名强制I​​PV4:

var uri = new Uri("somedomain.com");
var builder = new UriBuilder(uri);
var addresses = await Dns.GetHostAddressesAsync(uri.Host);    
builder.Host = addresses
                 .First(x => x.AddressFamily == AddressFamily.InterNetwork) //IPV4 only
                 .ToString(); 
var request = new HttpRequestMessage(HttpMethod.Get, builder.Uri);
request.Host = uri.Host;

也许有更好的方法。我无法使用 SocketsHttpHandler,因为我坚持使用 .NET Framework 4.5