出于分析目的,我想对大批量的IP执行反向DNS查找。 “大”的含义,每小时至少数万。我正在寻找提高处理速度的方法,即降低每批处理时间。
将Dns.GetHostEntry的异步版本包装到等待的任务中已经帮助了很多(与顺序请求相比),从而导致了appox的吞吐量。 100-200 IPs /秒:
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);
}
如何进一步提高处理率?
例如,有没有办法将一批IP发送到DNS服务器?
顺便说一下,我假设在封面下,异步方法使用了I/O Completion Ports - 如果我错了请纠正我。
答案 0 :(得分:4)
您好以下是一些提示,以便您可以改进:
我希望这会有所帮助。
答案 1 :(得分:1)
TPL Dataflow
的ActionBlock
,而不是一次性触发所有请求,等待所有请求完成。使用ActionBlock
MaxDegreeOfParallelism
高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});
自行决定同时启动多少次调用,从而更好地利用资源:的
Dns
我还建议添加缓存,并确保不要多次解析同一个ip。
当您使用.net的GetHostEntryAsync
类时,它会在DNS旁边包含一些后备(例如LLMNR),这使得它非常慢。如果您只需要DNS查询,则可能需要使用ARSoft.Tools.Net等专用库。
P.S:关于你的代码示例的一些评论:
FromAsync
代替ConcurrentDictionary