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

FastAPI同步异步接口性能压测结果一致问题排查

问题根源

你测试得到同步、异步接口性能一致,既不是对技术概念的理解有偏差,也不是代码编写错误,核心原因是当前压测的并发度太低,根本没有触达同步模式的性能瓶颈,两种模式都处于性能富余区间,自然表现一致。

先明确FastAPI+Uvicorn栈对两类端点的处理逻辑:

  • 对于async def定义的异步端点,请求会直接在worker的单线程事件循环中执行,遇到await标记的IO操作时会主动挂起协程,释放CPU给其他协程,理论上单worker可以同时处理成百上千个等待IO的请求,不需要额外创建线程。
  • 对于普通def定义的同步端点,框架不会让阻塞逻辑直接卡住事件循环,而是会自动把整个端点逻辑扔到worker关联的内置线程池中执行,每个请求占用一个独立线程,遇到阻塞IO(比如time.sleep、同步数据库调用)时只会阻塞当前工作线程,不会影响事件循环接收新请求。

你当前的测试配置是4个worker,压测并发是8,平均每个worker只需要同时处理2个请求:不管是事件循环同时挂2个协程,还是线程池开2个线程跑阻塞逻辑,都没有任何压力,8个请求几乎同时开始等待5秒、同时返回,80个请求刚好分10批跑完,总耗时50~55秒完全符合预期,两种模式自然不会有性能差异。

如何复现异步的性能优势

把启动命令的worker数改成1,排除多进程并行的干扰:

gunicorn main:app --workers=1 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000

再把压测并发提高到30以上(超过单worker默认线程池的大小,Python默认线程池大小通常为CPU核心数+4,最多不超过32):

ab -n 80 -c 40 http://localhost:8000/hello-async
ab -n 80 -c 40 http://localhost:8000/hello

这时候你就能看到明显差异:

  • 异步接口:40个请求会同时在事件循环中挂起等待5秒,80个请求分2批就能跑完,总耗时约10秒,RPS约8。
  • 同步接口:受限于线程池大小,同一时间最多只能跑N个请求(N为线程池最大线程数),如果N是8,就需要分10批跑完,总耗时约50秒,RPS约1.6,性能差距可达5倍。
疑问解答

1. 异步模式的理论性能上限

异步单worker模式没有线程数的硬限制,性能瓶颈主要来自三个层面:

  • 操作系统限制:最大文件描述符数量(每个TCP连接占1个fd,默认通常是1024,修改配置可以到几十万级别)、临时端口范围、服务器网络带宽。
  • 运行时限制:事件循环的调度开销,当并发协程数达到几万到几十万级别时,协程上下文切换、事件循环遍历等待队列的CPU开销会逐步升高,导致请求延迟上升。
  • 业务代码限制:如果在异步端点中写了阻塞逻辑(比如用time.sleep、调用同步数据库驱动没有加await、执行CPU密集运算),会直接阻塞整个事件循环线程,导致所有请求都被卡住,性能甚至不如同步模式。

2. 两类上限的测试方法

测试前统一固定为单worker,排除多进程调度的干扰,保持接口逻辑固定为等待5秒(排除业务逻辑波动影响):

  • 同步模式线程数上限测试:从低到高逐步提升压测并发数,记录每个并发档位的平均请求耗时、RPS。当平均请求耗时开始明显超过5秒(接口本身的处理时间)、RPS不再随并发数提升线性增长时,对应的并发数就是当前同步模式的线程处理上限——超出上限的请求会在线程池队列中排队等待,产生额外延迟。
  • 异步模式事件循环上限测试:确保接口是纯异步无阻塞逻辑,从低到高逐步提升压测并发数,直到出现连接被拒绝、请求报错,或者平均请求耗时明显超过5秒、RPS不再增长,此时的并发数就是当前配置下事件循环的处理上限,这个值通常是几千到几万级别,远高于同步模式的线程上限(通常几十到几百)。

注意:异步的性能优势只在高并发IO密集场景下才会体现,低并发下两种模式的表现几乎没有差异,盲目使用异步不会带来任何性能收益,反而会提升代码编写的出错概率。

内容的提问来源于stack exchange,提问作者Obi wan kenobi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 21:48:10