celery任务不执行的根源是broker连接失败或task未被worker正确注册,需检查celery_broker_url连通性、worker是否加载task模块、@app.task装饰器使用及导入时机。

celery 任务不执行,apply_async 返回 AsyncResult 却没进 worker
常见现象是调用 task.apply_async() 后控制台没日志、数据库没写入、Redis 里也查不到待消费任务。根本原因通常是 broker 连接失败或 task 名未被 worker 正确注册。
- 检查
CELERY_BROKER_URL是否指向可连通的 Redis/RabbitMQ,用redis-cli -u redis://... ping或curl -I验证服务可达 - 确保 worker 启动时加载了定义该 task 的模块,比如
celery -A myproject.celery_app worker中的myproject.celery_app必须 import 到 task 所在文件 - task 函数必须加
@app.task装饰器,且不能定义在if __name__ == "__main__"块内——worker 导入时不会执行那段代码 - 用
celery -A myproject.celery_app inspect active看 worker 是否在线、有无积压任务
本地开发用 task.delay() 和 apply_async() 的区别在哪
delay() 是 apply_async() 的语法糖,只支持位置/关键字参数;而 apply_async() 可传 countdown、eta、expires、queue 等调度控制参数。开发中容易误以为 delay() 更“轻量”,其实两者底层完全一致,只是封装层级不同。
-
add.delay(2, 3)等价于add.apply_async(args=[2, 3]) - 需要延迟 5 秒执行?必须用
add.apply_async(args=[2, 3], countdown=5),delay()不支持 - 指定队列(如
high_priority)只能通过apply_async(queue="high_priority"),delay()无法做到 - 若任务参数含不可序列化对象(如
datetime、自定义类实例),两者都会抛PickleError,不是delay()特有问题
使用 task.retry() 时重试没生效或无限循环
task.retry() 不是自动重试,它本质是抛出 Retry 异常并由 worker 捕获后重新入队。如果没 catch 异常、或异常类型不对、或 worker 配置禁用了重试,就会静默失败或直接退出。
- 必须在
try/except中显式调用self.retry()(注意带self),不能写成task.retry() - 默认重试次数是 3 次,超限后抛原始异常;可通过
max_retries=5或retry_kwargs={"max_retries": 5}调整 - 重试间隔默认是指数退避(1s → 2s → 4s),用
countdown可覆盖,比如self.retry(countdown=10)强制等 10 秒 - 若函数本身已捕获所有异常但没 re-raise,
retry()根本不会触发——它依赖异常传播机制
Django 项目里 Celery 配置容易漏掉的兼容点
Django 的 settings.py 和 Celery 的 celery.py 之间存在隐式耦合,尤其在 Django 4.2+ 和 Celery 5.3+ 组合下,django.setup() 调用时机和模块导入顺序稍有偏差,就会导致 ORM 报 AppRegistryNotReady。
立即学习“Python免费学习笔记(深入)”;
-
celery.py文件顶部必须先import os; os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings'),再import django; django.setup() - 所有 task 定义文件(如
tasks.py)不能在celery.py加载前就 import model,否则 Django app 尚未 ready -
CELERY_TASK_SERIALIZER = 'json'推荐显式设置,避免 pickle 在跨版本 Python 或多语言环境中出问题 - 若用
django-celery-beat,其PeriodicTask表需手动 migrate,且celery beat进程要单独启动,不随 worker 自动运行
异步任务的“实验性支持”往往卡在配置链最脆弱的一环:不是 Celery 本身不工作,而是 Django 没 setup、broker 地址写错、或者 task 被 import 了两次。这些地方改起来快,但排查时最容易反复绕圈。










