Celery + Eventlet pool并没有提升异步web请求的执行速度

Celery + Eventlet pool does not improve execution speed of asynchronous web requests

作为 mentioned in the celery docs,对于事件 I/O,例如异步 HTTP 请求,eventlet 池应该比 prefork 池更快。

他们甚至提到

"In an informal test with a feed hub system the Eventlet pool could fetch and process hundreds of feeds every second, while the prefork pool spent 14 seconds processing 100 feeds."

但是,我们无法生成与此类似的任何类型的结果。 运行 example tasksurlopencrawl 完全按照描述打开了数千个 url,看来 prefork 池几乎总是表现更好。

我们测试了各种并发(prefork 并发 200,eventlet 并发 200、2000、5000)。在所有这些情况下,使用 prefork pool.The 机器 运行 上的任务在更少的秒内完成是一台带有 RabbitMQ 服务器 运行ning.

的 2014 Macbook Pro

我们希望同时发出数千个异步 HTTP 请求,并且想知道 eventlet 池是否值得实施?如果是,我们还缺少什么?

结果 python -V && 点冻结 是:

Python 2.7.6
amqp==1.4.6
anyjson==0.3.3
billiard==3.3.0.20
bitarray==0.8.1
celery==3.1.18
dnspython==1.12.0
eventlet==0.17.3
greenlet==0.4.5
kombu==3.0.26
pybloom==1.1
pytz==2015.2
requests==2.6.2
wsgiref==0.1.2

使用的测试代码(几乎完全来自文档):

>>> from tasks import urlopen
>>> from celery import group
>>> LIST_OF_URLS = ['http://127.0.0.1'] * 10000 # 127.0.0.1 was just a local web server, also used 'http://google.com' and others
>>> result = group(urlopen.s(url)
...                     for url in LIST_OF_URLS).apply_async()

Eventlet 允许您拥有比 prefork 更高的并发性,甚至无需编写非阻塞式代码。 Eventlet 优于 prefork 的典型情况是当您有许多阻塞 I/O 绑定操作时(例如 time.sleeprequests.get 到高延迟网站)。您对本地主机或“http://google.com”的请求似乎得到的响应太快而无法被视为 I/O-bounded.

您可以试试这个玩具示例,看看基于 Eventlet 的池如何在 I/O 绑定操作中表现更好。

# in tasks.py add this function
import time

# ...

@task()
def simulate_IO_bound():
    print("Do some IO-bound stuff..")
    time.sleep(5)

运行worker同理,最终产生任务

from tasks import simulate_IO_bound

NUM_REPEAT = 1000

results = [simulate_IO_bound.apply_async(queue='my') for i in range(NUM_REPEAT)]
for result in results:
    result.get()

假设您有一个具有 100 个子进程的 prefork worker 和另一个具有 1000 个绿色线程的 worker,您将能够看到显着的差异。