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

FastAPI启动时如何异步下载大文件避免阻塞事件循环?

解决FastAPI启动时并行下载大文件不阻塞启动的问题

你当前的问题出在@app.on_event("startup")装饰的同步函数会阻塞worker的启动流程——直到下载完成,worker才会进入就绪状态处理请求。大文件下载耗时过长,直接导致worker启动超时,触发大量错误。

下面提供两种可行的解决方案:

方案一:使用后台线程(适合同步下载逻辑)

把下载逻辑放到独立线程中,启动线程后立刻返回,不阻塞startup事件的执行:

from fastapi import FastAPI
import threading
import requests

app = FastAPI()

items = {}
# 线程安全锁:如果下载线程需要修改共享变量(比如items),必须加锁防止竞态条件
items_lock = threading.Lock()

def download_large_file():
    try:
        # 替换为你的实际下载逻辑,这里以requests流式下载为例
        url = "https://example.com/your-large-file"
        with requests.get(url, stream=True) as resp:
            resp.raise_for_status()
            with open("large_file.bin", "wb") as f:
                for chunk in resp.iter_content(chunk_size=8192):
                    f.write(chunk)
        
        # 更新共享变量时加锁
        with items_lock:
            items["download_status"] = "completed"
    except Exception as e:
        # 记录下载错误,根据需求处理
        with items_lock:
            items["download_status"] = f"failed: {str(e)}"

@app.on_event("startup")
def startup_event():
    # 启动后台守护线程,主进程退出时线程会自动终止
    download_thread = threading.Thread(target=download_large_file, daemon=True)
    download_thread.start()

方案二:使用异步任务(适合异步下载逻辑)

如果你的下载库支持异步(比如aiohttp),可以用asyncio.create_task把下载任务丢到后台异步执行:

from fastapi import FastAPI
import asyncio
import aiohttp

app = FastAPI()

items = {}

async def download_large_file():
    try:
        url = "https://example.com/your-large-file"
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                resp.raise_for_status()
                with open("large_file.bin", "wb") as f:
                    async for chunk in resp.content.iter_chunked(8192):
                        f.write(chunk)
        
        items["download_status"] = "completed"
    except Exception as e:
        items["download_status"] = f"failed: {str(e)}"

@app.on_event("startup")
async def startup_event():
    # 创建异步任务,后台执行,不阻塞startup流程
    asyncio.create_task(download_large_file())

关键注意事项

  • 线程/任务的生命周期:使用守护线程或异步任务时,若FastAPI进程意外退出,未完成的下载会被终止。如果需要确保下载完成,可额外添加进程级的监控逻辑。
  • 共享资源安全:如果下载线程/任务需要修改全局变量(比如items),必须用锁(线程场景)或确保异步操作的原子性(异步场景),避免竞态条件。
  • 错误处理:务必给下载逻辑添加异常捕获,避免后台任务崩溃影响主应用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 11:00:04