Python异步反向DNS查找
我想在短时间内对大量的反向DNS进行查询。目前我已经用socket.gethostbyaddr和concurrent.futures线程池实现了异步查询,但性能还是不理想。比如说,这个脚本在处理2500个IP地址时花了大约22分钟。
我在想有没有更快的方法来完成这个任务,而不需要使用像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
请使用异步DNS,其他的选择会让你的性能很差。
3
我发现我主要的问题是IP地址无法解析,因此套接字没有遵循设定的超时时间,结果在30秒后失败。可以参考这个链接:Python 2.6 urlib2 超时问题。
adns-python不太适合,因为它不支持IPv6(没有补丁的话)。
经过一番搜索,我找到了这个:使用dnspython进行反向DNS查找,并在我的代码中实现了类似的版本(他的代码还使用了可选的线程池,并实现了超时功能)。
最后,我使用了dnspython和一个concurrent.futures线程池来进行异步的反向DNS查找(可以查看这个链接:Python:共享主机中的反向DNS查找和Dnspython:设置查询超时/生命周期)。通过设置1秒的超时,这样在处理2500个IP地址时,运行时间从大约22分钟缩短到了大约16秒。这么大的差异可能与套接字上的全局解释器锁和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 ""