在Celery中,如何阻止长时间延迟的任务阻止新的任务?

时间:2014-05-13 15:39:02

标签: python rabbitmq celery scheduling

我有两种任务。任务A由celerybeat每小时生成一次。它立即运行,并生成任务B的一千(或几千)个实例,每个实例都有一天的ETA。

启动时,任务A的实例运行并生成一千个B。从那以后,没有任何事情发生。我应该看到另一个A每小时运行,还有另外一千个B。但实际上我什么都看不见。

在冻结时,rabbitmqctl显示1000条消息,968准备好,32未确认。一小时后,有1001条消息,969准备好,32未确认。等等,每隔一小时就有一条新消息被归类为准备就绪。据推测,正在发生的事情是,工人正在预取32条消息但不能对它们采取行动,因为他们的ETA仍然在未来。与此同时,现在应该运行的新任务无法运行。

处理此问题的正确方法是什么?我猜我需要多个工作人员,也许还有多个队列(但我不确定后一点)。有更简单的方法吗?我试过摆弄CELERYD_PREFETCH_MULTIPLIER和-Ofail(正如这里讨论的那样:http://celery.readthedocs.org/en/latest/userguide/optimizing.html),但是无法让它继续下去。我的问题与此问题相同:[[Django Celery]] Celery blocked doing IO tasks

在任何情况下:我只能解决这个问题,因为我对任务的性质及其时间有很多了解。使用未来ETA的足够任务是否可以锁定整个系统似乎不是一个设计缺陷?如果我等待几个小时,然后杀死并重新启动工作程序,它再次抓取前32个任务并冻结,即使此时队列中的任务已准备好立即运行。一些组件是否应该足够聪明才能查看ETA​​并忽略不可运行的任务?

ADDENDUM:我现在认为当RabbitMQ 3.3与Celery 3.1.0一起使用时,问题就是一个已知错误。更多信息: https://groups.google.com/forum/#!searchin/celery-users/countdown|sort:date/celery-users/FiAAESOzezA/499OH-pylacJ

更新到Celery 3.1.1后,情况似乎更好。任务A每小时运行一次(好吧,它有几个小时)并安排任务B的副本。这些似乎正在填补工作人员:未确认消息的数量继续增长。我必须看看它是否可以不受限制地增长。

2 个答案:

答案 0 :(得分:1)

看起来这是一个可以通过路由解决的问题: http://celery.readthedocs.org/en/latest/userguide/routing.html

使用路由时,您可以拥有多个填充了不同类型任务的队列。如果您希望任务B不阻止更多任务A,您可以将它们分成具有不同优先级的单独工作队列,这样您的工作人员就可以在充满任务B的大队列上工作,但是当任务A到达时它将被下一个可用工人。

这样做的另一个好处是,您还可以为更多填充的队列分配更多的工作人员,而这些工作人员只会从指定的高容量队列中提取。

答案 1 :(得分:0)

您目前使用什么并发运行了多少名工作人员?

增加工作者的并发性可能有助于解决问题。如果线程x卡在任务A上,这需要花费很长时间或处于等待状态,则另一个线程可以处理其他预取任务

http://celery.readthedocs.io/en/latest/reference/celery.bin.worker.html#cmdoption-celery-worker-c