Celery任务子进程占满并发槽吗?
我正在运行一系列需要很长时间才能完成的重型 Celery 任务(这些任务会启动多个子进程),并且我设置了 CELERYD_CONCURRENCY = 4
,也就是说最多可以同时运行 4 个任务。最开始,确实有 4 个任务同时启动,这没问题。但是,当一些任务完成后,新的任务并不会立刻开始,直到更多的任务完成。结果,Celery 只保持 1 或 2 个任务在运行,直到所有任务都完成(这一点通过 Celery Flower 确认了)。
当我只运行一些简单的任务,比如默认的 Celery add
函数时,一切都按预期正常工作。
Celery 启动的子进程(它们和任务有相同的进程组 ID)是否也算在并发的任务数量里?有没有办法确保 Celery 只计算任务本身,而不算这些子进程?
1 个回答
2
Celery 默认使用预先分叉(prefork)作为执行池,每当你创建一个子进程(也就是再分叉一次),它就会计算当前正在运行的并发进程数量,也就是 CELERYD_CONCURRENCY
里设置的数字。
为了避免这个问题,你可以使用 eventlet,这样你就可以在每个任务中同时进行多个异步调用,只要你的任务里没有会阻塞的调用,比如 subprocess.communicate
。
为了进一步优化,你可以尝试把使用 subprocess.communicate
的任务分到一个不同的队列里,这个队列的工作者使用预先分叉,而其他不阻塞的任务则使用 eventlet 的工作者。