0

ウェブサイトの IP アドレスを解決するために Python スレッドを使用しています。これは、解決のための私のワーカー プロセスです。これはデーモンスレッドです。

def get_ip_worker():
    """This is the worker (thread) process for parsing ips, this process takes domain from the q processes it
    and then saves it to another q"""

    socket.setdefaulttimeout(3)
    while True:
        domain = domains_q.get()
        try:
            addr_info = socket.getaddrinfo(domain, 80, 0, 0, socket.SOL_TCP)
            for family, socktype, proto, name, ip in addr_info:
                if family == 2: #okay it's ipv4
                    ip, port = ip
                    processed_q.put((ip, domain))
                elif family == 10: #okay it's ipv6
                    ip, port, no_1, no_2 = ip
                    processed_q.put((ip, domain))
        except:
            pass
            #print 'Socket Error'

        domains_q.task_done()

編集: domain = domain_q.get() この行は、アイテムがキューで利用可能になるまでブロックします。

これを 300 スレッドで実行すると問題が発生します。負荷平均は問題ないようですが、単純な ls -la には 5 秒かかり、すべてが遅くなります。どこで私は間違えましたか?非同期またはマルチプロセッシングを使用する必要がありますか?

4

1 に答える 1

0

300 のスレッドで 300 の接続を並列に処理する必要が本当にあるのでしょうか? それほど多くのスレッドを作成しようとしたことはありませんが、問題になる可能性があります。そして、それは間違いなく問題を解決する良い方法ではありません. 通常、他のオプションがあります。まず、300 の接続をリッスンするのに 300 のスレッドは必要ありません。ハードウェアと OS で動作するように見えるスレッドをいくつか作成します。単一のスレッドを使用してメイン キューからリクエストを取得し、それらをスレッド プールからスレッドに渡します。

ところで、「キューからの取得」操作が実際にブロックされ、キューが空の場合に待機するかどうかを確認してください。そうでない場合、着信リクエストがあるかどうかに関係なく、ループが常に実行される可能性があります。

本当に必要なのは、ソケットの非ブロック モードと、ソケットselect.select()の 1 つが読み取りまたは書き込みの準備ができるまで待機するようなものです。そのコードは自分で書くことができます。そうしたくない場合は、gevent(またはtwisted) のような優れた非同期ネットワーク ライブラリが、プログラムのアーキテクチャを改善するのに役立つ可能性があります。マルチコア CPU の能力を最大限に活用することは別の問題ですが、少なくとも解決策があると聞いていますgevent(それらは、gunicornいくつかのプロセスを実行します。試したことがない)。しかし、実行速度ではなく、一度に多くのオブジェクトの I/O を効果的に待機する必要があるという問題が発生していると思います。もしそうなら、その目的で大量のスレッドを使用することは避けてください。これは通常、Python だけでなく、マルチスレッド プログラミングにより適したGILを持たない言語でも効果がありません。multiprocessingGIL を回避しますが、独自の実行コストが追加されるため、ここでは使用しないことをお勧めします。

于 2013-03-11T15:49:52.220 に答える