[英]Python Asynchronous Reverse DNS Lookups
我希望在很短的时间内进行大量的反向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)
但似乎没有效果。
我发现我的主要问题是IP无法解决,因此套接字不遵守设置超时并在30秒后失败。 请参阅Python 2.6 urlib2超时问题 。
由于缺乏对IPv6的支持(没有补丁), adns-python是不行的。
搜索后我发现: 使用dnspython反向DNS查找并在我的代码中实现了类似的版本(他的代码也使用可选的线程池并实现超时)。
最后,我使用带有concurrent.futures线程池的dnspython进行异步反向DNS查找(请参阅Python:共享主机中的反向DNS查找和Dnspython:设置查询超时/生命周期 )。 超时为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 ""
由于Global Interpreter Lock ,您应该使用ProcessPoolExecutor
。 https://docs.python.org/dev/library/concurrent.futures.html#processpoolexecutor
请使用异步DNS ,其他一切都会给你带来很差的性能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.