Python3.11下Celery多Worker异常及任务挂起问题求助
问题现象
在Windows环境搭配Python 3.11、Django、Redis 5.0.14.1、Celery 5.1.2时,执行命令:
celery -A project -l info -c 5
出现两个异常:
- Celery创建了7个以上的Worker进程(远超指定的
-c 5) - 任务被接收后直接挂起,无法执行完成
但使用协程池命令可正常运行:
celery -A worker -l info -P eventlet
且该多进程命令在Python 3.6环境下可正常工作。
环境信息
- 操作系统:Windows
- Python版本:3.11(异常)/ 3.6(正常)
- Celery版本:5.1.2
- Redis版本:5.0.14.1
- Django:未指定具体版本
相关代码
Celery实例代码(celery_app.py)
import os import django from celery import Celery from django.conf import settings os.environ.setdefault('FORKED_BY_MULTIPROCESSING', '1') os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_celery_test.settings') django.setup() celery_app = Celery('django_celery_test') celery_app.config_from_object('django.conf:settings', namespace='CELERY')
Django配置代码(settings.py)
CELERY_BROKER_URL = 'redis://localhost:6379/0' CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' CELERY_TASK_SERIALIZER = 'pickle' CELERY_RESULT_SERIALIZER = 'pickle' CELERY_ACCEPT_CONTENT = ['pickle', 'json'] CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24 CELERY_TIMEZONE = 'Asia/Shanghai' CELERY_TRACK_STARTED = True CELERY_IMPORTS = ( 'django_celery_test.celery_task' ) CELERY_QUEUES = ( Queue('default', Exchange('default'), routing_key='default'), )
问题原因分析
Windows与Python多进程机制的兼容性冲突
Python 3.8及以上版本在Windows系统中,multiprocessing模块默认使用spawn启动方式替代了旧版本的fork。而Celery默认的prefork池依赖Unix风格的fork机制,在Windows的spawn模式下会出现初始化异常:- 每个Worker进程都会重新执行整个Celery应用的初始化逻辑(包括Django的
django.setup()),导致进程创建逻辑混乱,出现超出指定数量的Worker spawn模式下进程间资源隔离更严格,Celery的任务调度逻辑无法正常传递任务上下文,导致任务挂起
- 每个Worker进程都会重新执行整个Celery应用的初始化逻辑(包括Django的
Python版本差异导致的行为变化
Python 3.6在Windows上默认使用模拟的fork启动多进程,与Celery的prefork池兼容性更好,因此可以正常运行。Celery版本的局限性
Celery 5.1.2发布于2021年,对Python 3.11(2022年发布)的兼容性支持不足,未针对Windows下的spawn模式做足够适配。
解决方法
方案1:使用协程池(推荐)
继续使用eventlet或gevent协程池,避开多进程的兼容性问题:
- 使用eventlet:
pip install eventlet celery -A django_celery_test -l info -P eventlet -c 5 - 使用gevent:
pip install gevent celery -A django_celery_test -l info -P gevent -c 5
方案2:升级Celery版本
将Celery升级到最新的5.x稳定版(如5.3.x),新版本对Python 3.11及Windows环境的兼容性更好,可能修复prefork池的异常问题:
pip install --upgrade celery
方案3:强制使用fork启动方式(不推荐)
在Celery应用初始化前强制设置多进程启动方式为fork,但Windows下的fork模拟存在稳定性风险,可能引发其他问题:
修改celery_app.py,添加:
import multiprocessing multiprocessing.set_start_method('fork', force=True)
方案4:调整Django初始化逻辑
避免在Celery主进程中提前执行django.setup(),改为让Worker进程自行初始化,但需要确保任务代码中能正确加载Django上下文。
内容的提问来源于stack exchange,提问作者shallow dreamer

