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

FastAPI中run_in_threadpool运行缓慢卡顿问题求助

解决FastAPI中run_in_threadpool运行缓慢卡顿的问题

核心问题分析

你的卡顿问题主要来自两个关键点:

  • 默认run_in_threadpool使用的线程池无线程数限制,当list_of_required_entry规模较大时,会创建大量线程,引发频繁上下文切换,直接拖慢性能。
  • foo函数中pandas的merge操作在事件循环线程执行,属于CPU密集型任务,会阻塞事件循环,导致整个服务响应变慢。

解决方案

1. 自定义线程池限制线程数量

创建全局ThreadPoolExecutor并设置合理的max_workers(建议设为CPU核心数的1-2倍),替换Starlette默认线程池,让run_in_threadpool自动使用受限线程池。

from concurrent.futures import ThreadPoolExecutor
import asyncio
from fastapi import FastAPI
import pandas as pd
from functools import reduce
import starlette.concurrency

# 自定义线程池,限制线程数
thread_pool = ThreadPoolExecutor(max_workers=4)

app = FastAPI()

# 启动时替换默认线程池
@app.on_event("startup")
async def startup():
    starlette.concurrency.DEFAULT_THREAD_POOL = thread_pool

# 关闭时清理线程池
@app.on_event("shutdown")
def shutdown():
    thread_pool.shutdown(wait=True)

2. 将所有CPU密集操作移至线程池

把bar调用和pandas的merge操作封装到线程函数中,避免在事件循环线程执行阻塞操作:

async def foo(param_1, param_2):
    def process_task(p1, p2):
        # 子线程中执行所有CPU密集操作
        df_a, df_b = bar(p1, p2)
        return df_a.merge(df_b, on='name', how='left')
    
    # 使用自定义线程池执行任务
    df = await asyncio.get_event_loop().run_in_executor(thread_pool, process_task, param_1, param_2)
    return df

3. 控制并发任务数(可选)

如果参数列表规模极大,可通过asyncio.Semaphore限制同时运行的任务数,避免瞬间压垮系统资源:

@app.get('/get_foo')
async def get_price_comparison():
    list_of_required_entry = [...]  # 你的参数列表
    tasks = []
    # 限制同时运行的任务数
    semaphore = asyncio.Semaphore(4)
    
    async def bounded_task(p1, p2):
        async with semaphore:
            return await foo(p1, p2)
    
    for param_1, param_2 in list_of_required_entry:
        tasks.append(asyncio.create_task(bounded_task(param_1, param_2)))
    
    data = await asyncio.gather(*tasks)
    data_dataframe = reduce(lambda left, right: pd.merge(left, right, on='name', how='left'), data)
    return data_dataframe.to_dict(orient='records')

关键注意事项

  • max_workers不要设置过大,过多线程会增加上下文切换开销,反而降低性能。
  • 所有pandas的CPU密集操作(如merge、groupby)必须放到线程池执行,严禁阻塞事件循环。
  • Semaphore的数值可根据硬件配置调整,平衡并发效率与资源占用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:40:20