Python异步反向DNS查找

时间:2014-06-07 05:06:54

标签: python django asynchronous reverse-dns

我希望在很短的时间内进行大量的反向DNS查找。我目前使用socket.gethostbyaddr和concurrent.futures线程池实现了异步查找,但仍然没有看到所需的性能。例如,脚本大约需要22分钟才能完成2500个IP地址。

我想知道是否有更快的方法可以做到这一点而不诉诸adns-python之类的东西。我发现这个http://blog.schmichael.com/2007/09/18/a-lesson-on-python-dns-and-threads/提供了一些额外的背景。

代码段:

ips = [...]
with concurrent.futures.ThreadPoolExecutor(max_workers = 16) as pool:
    list(pool.map(get_hostname_from_ip, ips))
def get_hostname_from_ip(ip):
    try:
        return socket.gethostbyaddr(ip)[0]
    except:
        return ""

我认为问题的一部分是许多IP地址没有解决和超时。我试过了:

socket.setdefaulttimeout(2.0)

但它似乎没有效果。

3 个答案:

答案 0 :(得分:3)

我发现我的主要问题是IP无法解决,因此套接字不遵守设置超时并在30秒后失败。请参阅Python 2.6 urlib2 timeout issue

由于缺乏对IPv6的支持(没有补丁),

adns-python 是不合适的。

搜索后我发现:Reverse DNS Lookups with dnspython并在我的代码中实现了类似的版本(他的代码也使用了一个可选的线程池并实现了超时)。

最后,我使用dnspython和concurrent.futures线程池进行异步反向DNS查找(请参阅Python: Reverse DNS Lookup in a shared hostingDnspython: Setting query timeout/lifetime)。超时为1秒时,2500个IP地址的运行时间从大约22分钟减少到大约16秒。差异很大可能归因于套接字上的Global Interpreter Lock和30秒超时。

代码段:

import concurrent.futures
from dns import resolver, reversename
dns_resolver = resolver.Resolver()
dns_resolver.timeout = 1
dns_resolver.lifetime = 1
ips = [...]
results = []

with concurrent.futures.ThreadPoolExecutor(max_workers = 16) as pool:
    results = list(pool.map(get_hostname_from_ip, ips))

def get_hostname_from_ip(ip):
    try:
        reverse_name = reversename.from_address(ip)
        return dns_resolver.query(reverse_name, "PTR")[0].to_text()[:-1]
    except:
        return ""

答案 1 :(得分:1)

答案 2 :(得分:0)

请使用asynchronous DNS,其他一切都会给你带来很差的表现。