大批量IP的反向DNS解析加速方法

5
对于分析目的,我想对大量IP执行反向DNS查找。 "大量"是指每小时至少数万个IP。 我正在寻找提高处理速率的方法,即降低每批处理时间。
Dns.GetHostEntry的异步版本包装成可等待任务已经有了很大的帮助(与顺序请求相比),导致吞吐量约为每秒100-200个IP:
static async Task DoReverseDnsLookups()
{
    // in reality, thousands of IPs
    var ips = new[] { "173.194.121.9", "173.252.110.27", "98.138.253.109" }; 
    var hosts = new Dictionary<string, string>();

    var tasks =
        ips.Select(
            ip =>
                Task.Factory.FromAsync(Dns.BeginGetHostEntry,
                    (Func<IAsyncResult, IPHostEntry>) Dns.EndGetHostEntry, 
                    ip, null)
                    .ContinueWith(t => 
                    hosts[ip] = ((t.Exception == null) && (t.Result != null)) 
                               ? t.Result.HostName : null));

    var start = DateTime.UtcNow;
    await Task.WhenAll(tasks);
    var end = DateTime.UtcNow;

    Console.WriteLine("Resolved {0} IPs in {1}, that's {2}/sec.", 
      ips.Count(), end - start, 
      ips.Count() / (end - start).TotalSeconds);
}

你有什么想法来进一步提高处理速度吗?

例如,是否有任何方法可以向DNS服务器发送一批IP地址?

顺便说一下,我假设在异步方法中使用I/O完成端口 - 如果我错了请纠正我。


2
你为什么要使用FromAsync而不是现有的Dns.GetHostEntryAsync - noseratio - open to work
@Noseratio 因为我没有看到它。 :/ 可能没有预料到同时有Begin/End和-Async版本.. - Max
2个回答

5

你好,以下是一些提示,可以帮助你提高效率:

  1. 本地缓存查询结果,因为这些信息通常在几天或甚至几年内不会发生变化。这样,您就不必每次都要重新解析。
  2. 大多数DNS服务器会自动缓存信息,所以下次解析将相当快速。通常缓存时间为4小时,至少在Windows服务器上是默认设置。这意味着,如果您在短时间内批量运行此过程,它将比您在一天内多次解析地址并允许缓存过期表现更好。
  3. 很好,你正在使用任务并行性,但你仍然在使用配置在你的机器上的相同DNS服务器进行查询。我认为使用两台使用不同DNS服务器的计算机将改善该过程。

希望这能帮助到你。


缓存肯定有帮助,实际上已经在做了(应该提到一下)。多个DNS服务器也是一个好主意。谢谢! - Max

2
  • 像往常一样,我建议使用TPL DataflowActionBlock而不是一次性发出所有请求并等待所有请求完成。使用具有高MaxDegreeOfParallelismActionBlock可以让TPL自行决定并发地调用多少个请求,这可能会更好地利用资源:

var block = new ActionBlock<string>(
    async ip => 
    { 
        try
        {
            var host = (await Dns.GetHostEntryAsync(ip)).HostName;
            if (!string.IsNullOrWhitespace(host))
            {
                hosts[ip] = host;
            }
        }
        catch
        {
            return;
        }
    },
    new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 5000});
  • 我建议您添加缓存,并确保不会重复解析相同的IP。

  • 当您使用.NET的Dns类时,它包含除DNS之外的一些回退(例如LLMNR),这使其非常缓慢。如果您只需要DNS查询,您可能需要使用专用库,如ARSoft.Tools.Net


P.S:关于您的代码示例的一些说明:

  1. 您应该使用GetHostEntryAsync而不是FromAsync
  2. 继续可能在不同的线程上运行,因此您应该真正使用ConcurrentDictionary

1
尝试了ARSoft.Tools.Net,它比System.Net.Dns快得多 - 至少快5倍。 - Max

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接