我正在使用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 = domains_q.get()此行在队列中阻止项目可用。
当我在300个线程上运行此问题时,Load Average似乎没问题,但简单的ls -la需要5秒,而且一切都很慢。我哪里做错了?我应该使用异步还是多处理?
答案 0 :(得分:0)
你真的需要300个线程并行处理300个连接吗?我从未尝试过创建那么多线程,但这可能是个问题。这绝对不是解决问题的好方法。通常还有其他选择。首先,您不需要300个线程来侦听300个连接。创建一些似乎适用于您的硬件和操作系统的线程。使用单个线程从主队列中检索请求,然后将它们传递给thread pool的线程。
BTW,检查你的“从队列中检索”操作是否真的阻塞并等待队列为空。如果不是,则可以一直执行循环,而不是取决于是否有传入请求。
您可能真正需要的是套接字的非阻塞模式以及类似select.select()
之类的东西,等待其中一个套接字准备好进行读取或写入。您可以自己编写该代码。如果您不急于这样做,那么像gevent
(或twisted
)这样的好的异步网络库可能有助于改进程序的体系结构。利用多核CPU的全部功能是一个单独的问题,但我听说有解决方案,至少对于gevent
(它们基于运行多个进程的gunicorn
;从未尝试过)。但我认为您遇到的问题不是执行速度,而是需要一次有效地等待许多对象的I / O.如果是这样,为了这个目的避免大量使用线程,它通常不仅在Python中有效,甚至在没有GIL的语言中更适合多线程编程。 multiprocessing
避免了GIL,但增加了自己的执行成本,所以我建议不要在这里使用它。