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 tasks、urlopen 和 crawl 完全按照描述打开了数千个 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.sleep
或 requests.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,您将能够看到显着的差异。
作为 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 tasks、urlopen 和 crawl 完全按照描述打开了数千个 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.sleep
或 requests.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,您将能够看到显着的差异。