3

短時間で多数の逆引き 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)

しかし、効果がないようです。

4

3 に答える 3

3

私の主な問題は、IP の解決に失敗したため、ソケットが設定されたタイムアウトに従わず、30 秒後に失敗したことであることがわかりました。Python 2.6 urlib2 タイムアウトの問題を参照してください。

adns-pythonは、IPv6 をサポートしていない (パッチなし) ため、使用できませんでした。

周りを検索した後、これを見つけました: dnspythonを使用した DNS ルックアップの逆引き と同様のバージョンをコードに実装しました (彼のコードはオプションのスレッド プールも使用し、タイムアウトを実装しています)。

最後に、非同期リバース DNS ルックアップ用に、concurrent.futures スレッド プールで dnspython を使用しました (「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 ""
于 2014-06-08T00:29:44.793 に答える
0

非同期 DNSを使用してください。それ以外では、パフォーマンスが非常に低下します。

于 2014-06-07T05:20:48.030 に答える