我想使用Celery作为我的任务的队列,所以我的网络应用程序可以排队任务,返回响应,同时处理任务/某天/ ...我构建了一种API,所以我不知道提前会有什么类型的任务 - 将来,可能会有处理HTTP请求的任务,另一个IO,以及消耗CPU的任务。关于这一点,我想在流程上运行Celery的工作者,因为这些是Python中的通用类型的并行性。
但是,我也想在我的任务中使用gevent,所以我可以有一个任务产生许多HTTP请求,等等。问题是,当我这样做时:
from gevent import monkey
monkey.patch_all()
芹菜停止工作。它开始,但没有任何任务可以有效排队 - 他们似乎去经纪人,但芹菜工人不收集它们并处理它们。只有开始和等待。如果我删除这些行并执行任务而没有任何gevent和并行化,一切正常。
我认为这可能是因为gevent补丁也在线程化。所以我试过
from gevent import monkey
monkey.patch_all(thread=False)
...但是Celery甚至没有启动,它在没有给出理由的情况下崩溃(启用了日志记录的调试级别)。
是否可以使用Celery将任务排入队列并在单个任务中执行某些操作?怎么样?我做错了什么?
答案 0 :(得分:19)
我认为启动任务的推荐方法如下。
python manage.py celery worker -P gevent --loglevel=INFO
Gevent需要尽早修补。
答案 1 :(得分:9)
您可以使用包含多个greenlet的多个线程运行芹菜,如下所示:
$ celery multi start 4 -P gevent -l info -c:1-4 1000
答案 2 :(得分:3)
根据我的奇怪经验,Celery Beat无法与具有gevent池的工作人员正常工作(计划任务被阻止并永远等待),除非您为Beat流程激活gevent monkey补丁。
但是,celery beat
不支持--pool=gevent
或-P gevent
选项。注入gevent monkey补丁的正确方法是使用curstomized celery
二进制文件,例如:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from gevent import monkey
monkey.patch_all()
import re
import sys
from celery.__main__ import main
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(main())
将其另存为celery-gevent
,然后按如下方式运行Beat服务:
celery-gevent beat --app=proj.celery:app --loader=djcelery.loaders.DjangoLoader -f /var/log/celery/beat.log -l INFO --workdir=/my/proj --pidfile=/var/run/celery/beat.pid
在proj.celery
中,您还应该修补Django连接以避免DatabaseError
:
from __future__ import absolute_import
import os
# Set the Django settings module for the 'celery' program
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings')
import django
# Load Django model definitions, etc
django.setup()
from django.db import connection
# Allow thread sharing to ensure that Django database connection
# works properly with gevent.
connection.allow_thread_sharing = True
from django.conf import settings
from celery import Celery
app = Celery('proj')
# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
(以上示例适用于Python 2.7.10,Celery 3.1.18,Django 1.8.2和gevent 1.0.2)
答案 3 :(得分:2)
据我所知,不可能。如果有人找到了更好的答案,我会接受它,而不是我的。
唯一的选择是将gevent也用作Celery工作者的后端。为了完成这样的事情,必须做的是在配置文件中添加以下内容:
CELERYD_POOL = 'gevent'
可以找到有关此选项的更多详细信息here。有关gevent池的更多信息是on this page。请注意,gevent池仍然标记为实验性的。我发现没有基准可用于比较不同任务的进程和异步gevent池(面向IO的任务,面向CPU的任务),但最后我意识到即使我的 CPU绑定任务实际上也会更多IO比CPU,因为我使用数据库来保存结果和数据库连接将是一个瓶颈,而不是计算部分。我将没有任何能够真正击中CPU的科学任务。