Celery 超时后没有将任务放回 RabbitMQ 队列

Posted

技术标签:

【中文标题】Celery 超时后没有将任务放回 RabbitMQ 队列【英文标题】:Celery did not put task back in RabbitMQ queue after timeout 【发布时间】:2015-11-29 19:44:46 【问题描述】:

我在 Heroku 上运行 Celery 工作者,其中一项任务达到了超时限制。当我手动重试时,一切正常,所以可能是连接问题。我使用 RabbitMQ 作为代理,并且 Celery 被配置为对任务进行后期确认(CELERY_ACKS_LATE=True)。我预计任务会返回到 RabbitMQ 队列并由另一个工作人员再次处理,但它没有发生。当工作人员超时时,我是否需要配置其他任何任务才能返回到 RabbitMQ 队列?

这里是日志:

Traceback (most recent call last): 
  File "/app/.heroku/python/lib/python3.4/site-packages/billiard/pool.py", line 639, in on_hard_timeout 
    raise TimeLimitExceeded(job._timeout) 
billiard.exceptions.TimeLimitExceeded: TimeLimitExceeded(60,) 
[2015-09-02 06:22:14,504: ERROR/MainProcess] Hard time limit (60s) exceeded for simulator.tasks.run_simulations[4e269d24-87a5-4038-b5b5-bc4252c17cbb] 
[2015-09-02 06:22:18,877: INFO/MainProcess] missed heartbeat from celery@420cc07b-f5ba-4226-91c9-84a949974daa 
[2015-09-02 06:22:18,922: ERROR/MainProcess] Process 'Worker-1' pid:9 exited with 'signal 9 (SIGKILL)' 

【问题讨论】:

【参考方案1】:

您似乎达到了 Celery 的时间限制。 http://docs.celeryproject.org/en/latest/userguide/workers.html#time-limits

默认情况下,Celery 不会为任务实现重试逻辑,因为它不知道重试对您的任务是否安全。也就是说,您的任务需要是幂等的,这样重试才能安全。

因此,由于任务失败而导致的任何重试都应在任务中进行。请参阅此处的示例:http://docs.celeryproject.org/en/latest/reference/celery.app.task.html#celery.app.task.Task.retry

您的任务可能会超时有几个原因,但您最清楚。 该任务可能已超时,因为处理数据的时间过长或获取数据的时间过长。

如果您认为该任务尝试连接到某些服务失败,我建议减少连接超时间隔并在您的任务中添加重试逻辑。如果您的任务处理数据花费的时间太长,请尝试将数据分成块并以这种方式处理。 Celery 对此有很好的支持:http://docs.celeryproject.org/en/latest/userguide/canvas.html#chunks

【讨论】:

以上是关于Celery 超时后没有将任务放回 RabbitMQ 队列的主要内容,如果未能解决你的问题,请参考以下文章

【celery】任务重复执行

我使用 Docker 部署 Celery 遇到的问题

调用挂在 Heroku 环境中的 celery 任务

celery正常启动后能收到任务但不执行任务的解决办法

Flask + Celery + Redis:消费者:无法连接到 amqp://guest:**@127.0.0.1:5672//:超时

celery使用group或者chord如何实时更新状态进度?