我正在使用2个芹菜实例。
第一个实例的配置是:
app = Celery('tasks', broker='amqp://guest@localhost//')
app.conf.update(
CELERY_RESULT_BACKEND='amqp',
CELERY_TASK_RESULT_EXPIRES=18000,
CELERY_ACCEPT_CONTENT=['json'],
CELERY_TASK_SERIALIZER='json',
CELERY_ROUTES={
'task_polling': {
'queue': 'task_polling_queue'
},
'save_shell_task': {
'queue': 'save_shell_task_queue'
},
'save_validation_chain_task': {
'queue': 'save_validation_chain_task_queue'
},
'do_work': {
'queue': 'do_work_queue'
},
'send_mail': {
'queue': 'send_mail_queue'
}
},
)
@shared_task(name='do_work', ignore_result=True)
def do_work(_serialized_task):
for bla in blala:
do_something()
is_canceled = send_task('save_validation_chain_task', [],
{'_params': my_params}).get() == True
使用以下命令启动:
celery -A tasks worker --loglevel=info -Q do_work_queue,send_mail_queue
和第二个:
app = Celery()
app.conf.update(
CELERY_RESULT_BACKEND='amqp',
CELERY_TASK_RESULT_EXPIRES=18000,
CELERY_ACCEPT_CONTENT=['json'],
CELERY_TASK_SERIALIZER ='json',
CELERYBEAT_SCHEDULE={
'periodic_task': {
'task': 'task_polling',
'schedule': timedelta(seconds=1),
},
},
CELERY_ROUTES={
'task_polling': {
'queue': 'task_polling_queue'
},
'save_shell_task': {
'queue': 'save_shell_task_queue'
},
'save_validation_chain_task': {
'queue': 'save_validation_chain_task_queue'
},
'do_work': {
'queue': 'do_work_queue'
},
'send_mail': {
'queue': 'send_mail_queue'
}
},
)
@shared_task(name='save_shell_task', ignore_result=True)
def save_shell_task(_result):
ShellUpdate(_json_result=_result).to_db()
@shared_task(name='save_validation_chain_task', ignore_result=False)
def save_validation_chain_task(_result):
return ValidationChainUpdate(_json_result=_result).to_db()
这个推出时:
celery -A my_prog worker -B --concurrency=1 -P processes -Q task_polling_queue,save_shell_task_queue,save_validation_chain_task_queue
问题是send_task(...).get()
没有收到结果。程序正在循环等待。
似乎芹菜没有收到队列结果或者没有等待正确的队列结果。问题肯定是由于-Q参数。您是否知道配置中的问题在哪里?
谢谢
编辑: 全球的想法是有两个不同源代码的芹菜实例。这就是为什么我决定枚举队列来删除依赖。我真的认为这就是为什么结果没有被消耗,因为我无法在命令中指定队列结果,因为这个结果具有每个结果的变量名(由celery动态为每个结果创建的队列)。任何为芹菜实例保留两个不同源代码的解决方案对我都有好处。我想避免使用另一个结果后端,因为体积非常低。
答案 0 :(得分:4)
您有正确的设置和配置。唯一的问题是您为ignore_result
任务设置了do_work
。
@shared_task(name='do_work', ignore_result=True)
设置此项时,即使您的任务由工作人员完成,任务的state
也始终为PENDING
。这就是为什么当你在该任务上执行.get()
时,它永远不会完成该语句的执行。
由于您只接受json
CELERY_ACCEPT_CONTENT=['json'],
CELERY_TASK_SERIALIZER ='json',
你还需要设置
CELERY_RESULT_SERIALIZER = 'json',
在你的两个配置中。
注意:强>
在您的情况下,您正在执行另一项任务中的.get()
任务。这应该避免。现在它会正常工作。来自celery 3.2 it will raise and error instead of warining。
如果符合您的需要,您可以使用chain来阻止启动同步子任务。调用chain时,它返回具有父属性的async_result对象。例如
task1 = add.s(1,2)
task2 = add.s(5)
task3 = add.s(10)
result = chain(task1 | task2 | task3)()
result.revoke(terminate=True) # revokes task3
result.parent.revoke(terminate=True) # revokes task2
result.parent.parent.revoke(terminate=True) # revokes task1
如果它们不合适,您可以使用信号来调用其他任务/功能。这是一个简单的例子(我还没有测试过这段代码)。
from celery.signals import task_success
@app.task
def small_task():
print('small task completed')
@app.task
@task_success.connect(sender=small_task)
def big_task(**kwargs):
print('called by small_task. LOL {0}'.format(kwargs))