我使用龙卷风实现了一个简单的网页报废,主要的想法是将所有网址插入到队列q
并生成多个工作人员,ping网址并检查它的状态(大多数网址不存在,即获得超时)
所有响应都插入到另一个队列q2
但是它无关紧要因为在完成所有工作之后处理此队列
我还使用线程实现了相同的方法,与concurrency
的编号相同,并且线程实现速度要快得多,尽管在等待来自Web的响应时踏板处于空闲状态,而龙卷风IOLoop应该是这种类型的最佳选择行为
from tornado import httpclient, gen, ioloop, queues
concurrency = 100
@gen.coroutine
def get_response(url):
response = yield httpclient.AsyncHTTPClient().fetch(url, raise_error=False)
return response
@gen.coroutine
def main():
q = queues.Queue()
q2 = queues.Queue()
@gen.coroutine
def fetch_url():
url = yield q.get()
try:
response = yield get_response(url)
q2.put((url, response.code))
finally:
q.task_done()
@gen.coroutine
def worker():
while True:
yield fetch_url()
for url in urls:
q.put(url)
print("all tasks were sent...")
# Start workers, then wait for the work queue to be empty.
for _ in range(concurrency):
worker()
print("workers spwaned")
yield q.join()
print("done")
if __name__ == '__main__':
io_loop = ioloop.IOLoop.current()
io_loop.run_sync(main)
线程impl很简单(没有多处理)并使用以下代码
for i in range(concurrency):
t = threading.Thread(target=worker, args=())
t.setDaemon(True)
t.start()
答案 0 :(得分:0)
为什么这可能会变慢,原因有几个:
异步编程的目标不是速度,它是可伸缩性。异步实现应该在高并发性水平下表现更好(特别是,它将使用更少的内存),但在低并发级别可能没有差异或线程可能更快。
Tornado的默认HTTP客户端是用纯python编写的,缺少一些对性能很重要的功能。特别是它无法重用连接。如果HTTP客户端请求的性能对您很重要,请改为使用基于libcurl的客户端:
tornado.httpclient.AsyncHTTPClient.configure('tornado.curl_httpclient.CurlAsyncHTTPClient')
有时即使在异步HTTP客户端中DNS解析也会阻塞,这会限制有效的并发性。在Tornado 5.0之前,Tornado的默认HTTP客户端就是如此。对于基于curl的客户端,它取决于libcurl的构建方式。您需要使用c-ares
库构建的libcurl版本。上次我看起来这在大多数Linux发行版上都没有默认完成。