芹菜结果,不工作

时间:2014-11-14 16:26:55

标签: python rabbitmq celery

我正在使用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动态为每个结果创建的队列)。任何为芹菜实例保留两个不同源代码的解决方案对我都有好处。我想避免使用另一个结果后端,因为体积非常低。

1 个答案:

答案 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))