无法解析DNS(有时?)

时间:2014-06-22 19:39:31

标签: c# windows multithreading dns

鉴于一个应用程序并行请求100个URL一次为10000个URL,我将收到50-5000个以下错误:

  

无法解析远程名称' www.url.com'

我知道错误意味着DNS服务器无法解析网址。但是,对于每次运行,无法解析的URL数量会发生变化(范围从50到5000)。

我提出的请求太快了吗?我甚至可以这样做吗? - 在功能更强大的服务器上运行相同的测试,显示只有10个网址无法解析 - 这听起来更加真实。

执行并行请求的代码:

var semp = new SemaphoreSlim(100);
var uris = File.ReadAllLines(@"C:\urls.txt").Select(x => new Uri(x));

foreach(var uri in uris)
{
   Task.Run(async () =>
   {
      await semp.WaitAsync();
      var result = await Web.TryGetPage(uri); // Using HttpWebRequest
      semp.Release();
   });   
}

2 个答案:

答案 0 :(得分:4)

我敢打赌,你不知道HttpWebRequest的DNS查询(这是所有.net http apis的基石)同步发生,甚至进行异步请求时(烦恼,正确) ?)。这意味着立即触发许多请求会导致严重的ThreadPool压力和大量延迟。这可能会导致意外超时。如果您真的想要解决问题,不要使用.net dns实现。您可以使用third party library来解析主机并使用ip而不是主机名创建webrequest,然后在触发请求之前手动设置主机头。您可以通过这种方式实现 更多 更高的吞吐量。

答案 1 :(得分:3)

听起来好像你正在淹没你的本地DNS服务器(用行话,你的本地递归DNS解析器)。

当您的程序发出DNS解析请求时,它会将端口53数据报发送到本地解析程序。该解析器通过从其缓存中回复或递归地将请求重新发送到已被识别为可能具有您正在查找的记录的其他解析器来响应。

因此,您的多线程程序导致大量数据报飞来飞去。 Internet协议主机和路由器通过丢弃数据报包来处理拥塞和过载。这就像在桥上铲起汽车来处理桥上的交通堵塞。在过载的情况下,一些数据包就会消失。

因此,如果他们的数据包丢失,则由端点软件使用数据报协议再次尝试。这就是TCP的目的,即使它只能与数据报进行通信,它也能提供无错数据流的假象。

因此,当您的某些DNS请求解决方案失败时,您的程序将需要再次尝试。您是数据报端点,因此您拥有重试的责任。我怀疑当你的一些请求超时时,.net库会让你失败,因为你的数据报被丢弃了。

现在,重要的是这里。与您的一样,数据报端点程序也负责实施拥塞控制。 TCP使用其滑动窗口系统自动执行此操作,其算法称为慢启动/指数退避。如果TCP没有这样做,所有互联网路由器将一直拥挤。这个算法是由Van Jacobson设想的,你应该去看看它。

与此同时,您应该在批量DNS查找程序中实现它的简单形式。这是你如何做到的。

  1. 从批量大小开始,比方说,5次查找。
  2. 每次成功恢复整批时,请为下一批将批量增加一个。这是一个缓慢的开始。只要您没有拥堵,就会增加网络负载。
  3. 每次无法解析名称时,请将下一批次的大小减半。因此,例如,如果您的批量大小为30并且您遇到了故障,那么您的下一批次大小将为15.这是指数退避。您可以通过大幅降低网络负载来应对拥塞。
  4. 实现100的最大批量大小只是为了避免过多的猪,看起来像是对DNS系统的粗略拒绝服务攻击。
  5. 前一段时间我有一个类似的项目,这个策略对我有用。