0

我正在使用 python 线程来解析网站 IP 地址。这是我的解决工作流程。这是一个守护线程。

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 个连接。创建许多似乎可以在您的硬件和操作系统上运行的线程。使用单个线程从主队列中检索请求,然后将它们从线程池传递给线程。

顺便说一句,如果队列为空,请检查您的“从队列中检索”操作是否真的阻塞并等待。如果没有,则循环可能一直执行,而不取决于是否有传入请求。

您可能真正需要的是套接字的非阻塞模式以及诸如select.select()等到您的一个套接字准备好读取或写入的东西。您可以自己编写该代码。如果您不急于这样做,可能一个好的异步网络库(如gevent(或twisted))可以帮助改进程序的体系结构。利用多核 CPU 的全部功能是一个单独的问题,但我听说有一些解决方案,至少对于gevent(它们基于gunicorn运行多个进程;没试过)。但我认为您遇到的问题不是执行速度,而是需要一次有效地等待许多对象的 I/O。如果是这样,请避免为此目的大量使用线程,它通常不仅在 Python 中无效,甚至在更适合多线程编程的没有GIL的语言中也是无效的。multiprocessing避免了 GIL 但增加了自己的执行成本,所以我建议不要在这里使用它。

于 2013-03-11T15:49:52.220 回答