FastAPI模型预测服务低负载下部分请求10s超时问题咨询
starlette.exceptions:ExceptionMiddleware.__call__ 耗时说明
该中间件是FastAPI底层依赖Starlette的最外层全局异常捕获中间件,会包裹整个请求处理的全链路:从请求进入服务、路由匹配、业务逻辑执行、到最终响应返回的完整过程都会被它覆盖。链路追踪统计的该段耗时本质是整个请求的总处理耗时,并非中间件本身执行逻辑慢,只是所有内部逻辑的耗时都被统计到了最外层的中间件上。
低负载下请求超时的核心原因
- 配置不生效问题:你当前使用的
UvicornWorker属于异步worker类型,gunicorn配置中的threads参数仅对同步worker生效,对异步worker的线程池配置没有任何作用。模型预测属于典型的CPU密集型操作,如果你将推理逻辑写在普通同步路由(未加async修饰的函数)中,请求会被提交到Uvicorn默认的线程池执行,受Python GIL锁限制,同进程内多个CPU密集型任务无法并行执行,只能串行排队,会直接拉长请求等待时长。 - 模型加载时机问题:如果你的模型采用懒加载策略(即第一次请求进来时才加载模型到内存),首次请求的耗时会包含数秒的模型加载时间,很容易触发超时。
- 上游超时配置不匹配:你配置的gunicorn超时为60秒,而请求出现的是10秒超时,说明超时规则大概率来自上游的Nginx、负载均衡或API网关,这类中间层的默认超时通常为10~30秒,和服务侧的超时配置不匹配也会导致请求提前被中断。
- 进程资源竞争:你配置的worker数量为4,如果服务器CPU核心数少于4,多worker会带来额外的CPU上下文切换开销,反而会降低推理效率。
优化建议
- 调整服务配置:CPU密集型场景下,worker数量设置为和服务器CPU核心数一致即可;如果所有路由都是同步推理逻辑,可直接改用gunicorn的同步worker,此时
threads参数才会生效,单worker线程数设为1即可,避免GIL竞争。 - 预加载模型:将模型加载逻辑放到FastAPI的生命周期事件中,在服务启动阶段就完成模型加载,避免请求阶段的冷启动开销。
- 对齐超时配置:将上游网关/负载均衡的超时时间调整到和服务侧60秒的配置一致,避免请求提前被中断。
- 优化推理逻辑:如果使用PyTorch/TensorFlow等框架,可设置
OMP_NUM_THREADS、MKL_NUM_THREADS等环境变量限制模型内部的线程数,避免和服务进程的线程产生资源竞争。
内容的提问来源于stack exchange,提问作者Riley Hun
相关产品推荐
相关产品推荐

