Celery shared_task运行卡住,执行一次普通task后才正常问题求助
问题根本原因
你遇到的是Celery @shared_task 装饰器的懒注册机制导致的问题:
@shared_task本身不会直接绑定到你的项目Celery实例上,它会先把任务存入临时注册表,等待Celery实例完成最终初始化后,才会批量把这些临时任务注册到实例上。- 你定义的
@app.task绑定的普通任务,第一次被调用时会强制触发Celery实例的最终初始化流程,这时候所有待注册的shared_task才会完成挂载,worker才能识别到这些任务。 - 首次调用
shared_task时,Celery实例还未完成初始化,任务没有被注册到worker的可执行列表中,就会出现无限期挂起的情况。
你项目根目录的__init__.py作用是正确的:它将Celery实例暴露到项目根模块,保证Django启动时可以加载到Celery实例,避免任务找不到实例的问题,只是缺少了强制完成初始化的步骤。
修复方案
直接在celery.py的autodiscover_tasks()调用后新增一行强制初始化代码即可:
app.autodiscover_tasks() app.finalize() # 新增这行,强制完成Celery实例初始化,提前注册所有shared_task
排查思路
如果修改后问题仍然存在,可以按以下步骤排查:
- 查看Celery worker启动日志,确认启动阶段是否有
debug_shared_task的注册记录,如果没有则说明任务注册流程仍然有问题 - 不要在
celery.py中使用@shared_task装饰器,该装饰器的设计目的是给其他Django子应用的任务使用,避免每个子应用都导入Celery实例,celery.py内部的任务直接用@app.task即可 - 检查所有使用
@shared_task的子应用,是否被Celery的自动任务扫描覆盖,可在autodiscover_tasks中显式指定要扫描的应用列表:app.autodiscover_tasks(['app1', 'app2', ...])
内容的提问来源于stack exchange,提问作者Falcondance
相关产品推荐
相关产品推荐

