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

FastAPI+Uvicorn在Docker中运行异常:后台任务完成才响应

FastAPI后台任务在Docker中阻塞API响应的解决方法

问题描述

开发的FastAPI应用支持异步视频上传,本地macOS运行时,API接收请求后立即返回响应,视频处理在后台执行;但部署到Docker容器后,API会等待后台视频处理完成才返回响应,不符合预期。简化代码如下:

from fastapi import FastAPI, BackgroundTasks, UploadFile, File
import uvicorn
from some_module import process_video

app = FastAPI()

@app.post("/upload/")
async def upload_video(background_tasks: BackgroundTasks, video: UploadFile = File(...)):
    background_tasks.add_task(process_video, video.file)
    return {"message": "Processing started"}

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.1", port=8000)

原因分析

  1. Uvicorn运行配置问题:本地默认可能使用多worker进程,而Docker中如果以单worker运行,后台任务会阻塞当前worker进程,导致API响应被延迟。
  2. UploadFile对象生命周期问题:video.file是请求上下文内的临时文件句柄,请求结束后可能被回收,直接传给后台任务可能引发异常或强制进程等待任务完成。
  3. BackgroundTasks局限性:FastAPI内置的BackgroundTasks依赖当前worker进程执行,仅适合轻量短耗时任务,若视频处理过重,会占用worker资源影响响应时机。

解决方案

1. 修正Uvicorn运行配置

  • 确保Docker中Uvicorn使用多worker进程启动,避免单进程被阻塞:
    修改启动代码:
    if __name__ == "__main__":
        uvicorn.run(app, host="0.0.0.0", port=8000, workers=2)
    
    或在Dockerfile的启动命令中指定worker数:
    CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "2"]
    
    注意:原代码中host="0.0.0.1"错误,Docker容器需绑定0.0.0.0才能被外部访问。

2. 先保存文件再处理

避免直接传递请求上下文内的文件句柄,先将上传文件保存到容器本地,再把文件路径传给后台任务:

from fastapi import FastAPI, BackgroundTasks, UploadFile, File
import uvicorn
import shutil
from pathlib import Path
from some_module import process_video

app = FastAPI()

@app.post("/upload/")
async def upload_video(background_tasks: BackgroundTasks, video: UploadFile = File(...)):
    # 创建临时目录保存上传文件
    temp_dir = Path("/tmp/video_uploads")
    temp_dir.mkdir(exist_ok=True)
    temp_file = temp_dir / video.filename
    
    with temp_file.open("wb") as buffer:
        shutil.copyfileobj(video.file, buffer)
    
    # 将文件路径传给后台任务
    background_tasks.add_task(process_video, str(temp_file))
    return {"message": "Processing started"}

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000, workers=2)

提示:在process_video函数末尾记得删除临时文件,避免容器磁盘被占满。

3. 改用专业异步任务队列

如果视频处理是耗时较长的重任务,建议放弃FastAPI内置的BackgroundTasks,改用Celery配合Redis或RabbitMQ作为任务队列,彻底解耦API请求和任务执行流程,避免容器环境下的进程阻塞问题。

内容的提问来源于stack exchange,提问作者Geraud Kameni

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 22:30:13