我有一个并发为4的工作者。我看到4个进程在花开始,一切看起来都不错。
如果我在shell中执行此操作,那么我会看到4个工作人员执行任务,其余部分保留,并且每次处理4个,直到队列为空。
[my_task.apply_async() for i in xrange(10)]
但是,如果我逐行执行此操作,则只会对前两个任务进行积极处理,从那时起,它一次只处理两个任务。
my_task.apply_async()
my_task.apply_async()
my_task.apply_async()
my_task.apply_async()
...
有什么想法吗?
答案 0 :(得分:3)
通常这是因为子进程填满了并发槽。 Celery默认使用prefork作为执行池,每次生成一个任务的子进程(另一个fork)时,它都算作一个正在运行的进程来填充并发插槽。
避免这种情况的最简单方法是using eventlet,这将允许您在每个任务上产生多个异步调用。但是,这要求您的任何任务都没有阻塞调用,例如subprocess.communicate
,因为它们会阻止所有任务。
否则,如果您有必要的阻止调用,并且您知道您的任务一次只有一个正在运行的子进程,则可以将CELERYD_CONCURRENCY
设置为double(8
)并设置一个开始任务的时间限制,因此8个任务不会立即开始(例如@app.task(rate_limit='10/m')
)。但是,这有点像黑客,使用eventlet绝对是首选。