PAYATHON 2026

Celery 任务调用 multiprocessing 库时如何并行运行?

数据小陈

结论

Celery 不会自动把一个任务拆成多个 Celery 任务,也不会把任务内部通过 multiprocessing 创建的进程分派给其他 Celery worker。外部库创建的进程由它在当前 worker 主机上管理。

如果外部库会创建子进程,而你又无法修改它的实现,可以尝试让 Celery 使用 threads 或 solo pool,再由外部库负责进程级并行。这种配置仍可能用到多个 CPU 核心:Celery 的线程池并发运行任务,multiprocessing 创建的子进程也可以使用多个核心。前提是外部库能在目标操作系统和进程启动方式下正常创建子进程。

为什么 prefork 可能失败

Celery 的 prefork pool 会在 worker 子进程中执行任务。Python multiprocessing 不允许 daemon 进程再创建子进程,因此可能报错:

daemonic processes are not allowed to have children

如果外部库在任务执行时调用 multiprocessing 创建进程,就可能触发这个限制。是否报错取决于 Celery 使用的 pool、运行环境和库的实现。可以先检查完整 traceback,确认错误是否发生在创建子进程时。

可尝试的运行方式

使用 threads pool

celery -A your_app worker -P threads --concurrency=4

这里的 --concurrency 限制同时运行的 Celery 任务数,不限制外部库创建的子进程数。每个任务仍可能通过 mp_func(n_proc) 启动多个进程。

使用 solo pool

如果希望 Celery 一次只运行一个任务,可以尝试:

celery -A your_app worker -P solo

任务仍由外部库在 worker 所在主机上创建进程。solo 不会并行运行多个 Celery 任务,适合先验证调用路径,或用于并发要求较低的情况。能否创建子进程仍需在目标环境中确认。

计算总并发与资源

使用 threads 时,Celery 的任务并发数会和任务内部的进程数叠加。例如,同时运行 4 个任务,每个任务最多创建 3 个子进程,就可能同时有多组工作进程运行。实际进程数取决于外部库的实现。应限制 Celery 的 --concurrency 和传给 mp_func 的进程数,并留意 CPU、内存和进程数上限,避免并发过多。

需要跨 worker 分发时

multiprocessing 不会把单个计算任务的不同部分分发到多台机器。通常需要把计算拆成多个可独立执行的 Celery 任务,再汇总结果;也可以让外部库使用支持跨机器调度的执行后端。前一种方式需要调整任务边界,后一种则取决于外部库支持的接口。

如果不能修改外部库,且只需在单台机器上利用多个核心,可以先尝试 threads 或 solo pool,并在目标环境中验证子进程能否启动。若要把同一任务的工作量分配到不同 worker,就需要通过 Celery 任务编排或其他分布式执行机制来实现。

备注:内容仅供参考。