代码之家  ›  专栏  ›  技术社区  ›  tigrou

如何使用HttpClient改进慢速DNS?

  •  0
  • tigrou  · 技术社区  · 4 年前

    我有一个特定域名的请求需要很长时间才能完成:平均22秒。请求本身不会返回大量数据。

    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条目将在缓存中停留很长一段时间)。此外,为什么DNS在使用时对该域如此缓慢 HttpClient ?如果我尝试使用Chrome访问该域,它会非常快(即使在刷新DNS和清除缓存之后)。使用在线服务对该域进行DNS查找也非常快。报告的TTL为60分钟。


    编辑:我试着增加 ServicePointManager.DnsRefreshTimeout (默认设置为2分钟)。但这无济于事。

    使命感 Dns.GetHostEntry("somedomain.com") 是即时的,并返回正确的IP。我不知道为什么请求 HttpClient 太慢了。

    1 回复  |  直到 4 年前
        1
  •  1
  •   tigrou    4 年前

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

    Dns.GetHostEntry("somedomain.com")
    

    首先,它尝试使用IPV6进行连接。最终,超时发生。然后它尝试IPV4(并且它工作)。这就解释了为什么它如此缓慢。到目前为止,我找到的解决方案是通过自己解析域名来强制IPV4:

    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

        2
  •  0
  •   Hrca12    4 年前

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

        3
  •  0
  •   56ka    4 年前

    使用的其他工作解决方案 SocketsHttpHandler HttpClient 此处: https://stackoverflow.com/a/70475741/1529139

    它在连接时使用IPv4 over IPv6。

    它为我完成了任务