You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法运行Celery定时任务:FastAPI+Celery+Docker Compose部署场景下的任务执行异常求助

排查Celery定时任务不执行+Redis连接问题的解决方案

我来一步步帮你拆解和解决遇到的这几个关联问题:

1. 先解决本地启动Worker的Redis连接错误

你在本地终端启动Worker时碰到的getaddrinfo failed错误,原因很直接:Docker Compose里的redis服务名只有在Docker内部网络才有效,本地机器无法解析这个域名。

  • 解决方案分两种场景:
    • 如果是在Docker外部启动Worker:把.env里的CELERY_BROKER_URL和CELERY_RESULT_BACKEND改成redis://localhost:6379/0和redis://localhost:6379/1
    • 如果是通过Docker Compose启动Worker(更推荐,保持环境一致性):确保你的celery_worker服务在docker-compose.yml里正确加载了.env文件,并且和redis服务处于同一个网络(默认Compose会创建全局网络,只要没自定义隔离网络就没问题)

2. 定时任务调度后不执行的核心原因:任务名称不匹配!

看你的workers.py代码细节:

  • Beat调度配置里指定的任务名是"start_etl"
  • 但你给start_etl函数加的装饰器是@celery.task(name="ETL pipeline")

Celery Beat是严格根据任务名称来触发Worker执行的,两者名称完全不匹配,Beat调度的任务找不到对应的Worker任务,自然不会有执行记录!

  • 修复方案二选一:
    选项1:修改Beat调度的任务名,和装饰器的name保持一致:
    celery.conf.beat_schedule = {
        "run_etl_task_every_5_minutes":{
            "task": "ETL pipeline",  # 和装饰器的name参数对齐
            "schedule": crontab(minute="*/5")
        }
    }
    
    选项2:去掉装饰器的name参数,让Celery自动用函数的全模块路径作为任务名:
    @celery.task  # 移除name参数
    def start_etl():
        # ... 你的原有代码
    
    此时Beat调度里的"task"要改成"etl.workers.start_etl"(根据你的实际模块路径调整,确保Worker能识别这个任务)

另外要牢记:Beat只负责调度任务,真正执行任务的是Worker,必须同时运行Celery Beat和Celery Worker,只启动Beat的话任务永远不会被执行。

3. Flower Inspect调用失败的衍生问题

这个问题基本是前面两个问题的连锁反应:

  • 如果Worker没正常连接到Redis,Flower无法获取Worker的状态信息

  • 如果Flower和Worker不在同一个Docker网络,也会导致通信失败

  • 解决方案:

    • 先确保Worker已经正常启动并连接到Redis(解决前面两个问题后再验证)
    • 在docker-compose.yml里,把flower服务和celery_worker、redis放在同一个网络下(默认Compose的全局网络即可)
    • 启动Flower时指定正确的Broker地址,比如在Compose里这么配置:
      flower:
        image: mher/flower
        command: celery flower --broker=${CELERY_BROKER_URL}
        ports:
          - "5555:5555"
        depends_on:
          - redis
          - celery_worker
        env_file:
          - .env
      

额外踩坑点:FastAPI接口的访问地址

你的start_etl函数里用了http://localhost:8000/video_operation,但如果Celery Worker是在Docker容器里运行的,这里的localhost指的是Worker容器本身,而不是你的本地机器。

  • 修复方案:把URL改成http://app:8000/video_operation(因为你的FastAPI服务容器名是app,Docker内部可以通过容器名直接访问)

总结排查步骤

  1. 区分本地/容器环境,修正Redis连接地址
  2. 统一Celery任务名称(Beat调度名和Worker任务名必须一致)
  3. 确保同时运行Beat和Worker(推荐用Docker Compose统一管理所有服务)
  4. 修正FastAPI接口的访问地址(容器内用服务名/容器名)
  5. 验证Flower和Worker在同一个网络,Broker地址配置正确

内容的提问来源于stack exchange,提问作者Renat Abdrakhmanov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 16:27:29