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

FastAPI后台任务阻塞:新请求需等待旧请求完成后才响应

FastAPI后台长任务阻塞请求的解决方法

问题场景

我尝试在后台执行长任务the_longer_function,期望API将任务加入后台后立即返回响应,无需等待任务完成。但实际观察到,当前置请求未完成时,新请求会被阻塞,必须等前置请求完成才返回响应。试过async、trio、并行和并发等方式都未解决。

现有代码

路由处理代码

@app.post("/something/something_test", response_class=JSONResponse)
@validate_token
async def home(request: Request, background_tasks: BackgroundTasks):
    try:
        request_params = await request.json()
        background_tasks.add_task(the_longer_function, request_params)

        return JSONResponse({
            "Result": "Execution Started!"
        }, status_code=200)
    except Exception as ex:
        return {
            "Result": f"Error in starting execution. Error {ex}"
        }

长任务函数

def the_longer_function(request_params):
    variable = None
    try:
        variable = request_params.get('variable', None)
        executionId = str(uuid.uuid4())
        bot_message['ExecutionId'] = executionId
        """
        耗时业务逻辑
        """
        publish_bot_scan_data(request_params, variable)
    except (JSONDecodeError, Exception) as ex:
        log.error(f"Error {ex}")

问题原因

FastAPI的BackgroundTasks默认在事件循环线程中执行任务,而the_longer_function是同步阻塞函数,其中的耗时业务逻辑会彻底卡住事件循环,导致后续请求无法被处理,必须等待当前任务执行完毕。

解决方案

方案1:用asyncio.to_thread将同步任务移至线程池

将同步任务放到独立线程执行,避免阻塞事件循环,修改路由中的任务添加逻辑即可:

import asyncio

@app.post("/something/something_test", response_class=JSONResponse)
@validate_token
async def home(request: Request, background_tasks: BackgroundTasks):
    try:
        request_params = await request.json()
        # 用asyncio.to_thread把同步任务委托给线程池
        background_tasks.add_task(asyncio.to_thread, the_longer_function, request_params)

        return JSONResponse({
            "Result": "Execution Started!"
        }, status_code=200)
    except Exception as ex:
        return JSONResponse({
            "Result": f"Error in starting execution. Error {ex}"
        }, status_code=500)

注意:如果the_longer_function中使用了全局变量(如bot_message),需要处理线程安全问题,建议通过参数传递替代全局变量,或添加线程锁。

方案2:使用独立任务队列(生产环境推荐)

对于超长时间运行的任务,建议使用Celery、RQ等任务队列框架,结合Redis或RabbitMQ作为消息中间件,将任务完全脱离FastAPI进程执行。这种方式能彻底避免任务对API服务的影响,还支持任务监控、重试等功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 00:25:54