FastAPI经常被提到的一个特点就是支持异步。

但实际用的时候,很多人容易产生一个误解:

只要把def改成async def,程序就会自动变快。

其实不是这样。

异步真正有价值的地方,是处理大量I/O等待。

什么是I/O等待

一个API请求可能需要:

调用第三方API
 ↓
等网络
 ↓
返回结果

或者:

查询数据库
 ↓
等数据库
 ↓
返回结果

等待期间CPU实际上没多少事要做。

如果程序能在等待的时候处理其他请求,就能提高资源利用率。

async def

FastAPI可以直接定义异步接口:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {
        "message": "hello"
    }

如果里面调用的也是异步API:

@app.get("/data")
async def get_data():
    result = await some_async_request()

    return result

那整个调用链就能保持异步。

多个请求可以并发

比如要请求三个互不依赖的服务:

a = await get_a()
b = await get_b()
c = await get_c()

这里实际上是:

get_a
 ↓
等待

get_b
 ↓
等待

get_c
 ↓
等待

如果三个请求可以同时发,那更适合:

import asyncio

a, b, c = await asyncio.gather(
    get_a(),
    get_b(),
    get_c()
)

这样三个任务可以并发执行。

并发不等于无限制并发

这里有个很容易踩的坑。

比如有10,000个URL:

await asyncio.gather(
    *[fetch(url) for url in urls]
)

理论上看起来很漂亮。

但实际上可能出现:

连接数暴涨
内存上涨
目标服务器压力过大
本地文件描述符耗尽
请求大量失败

所以实际项目里通常要限制并发数量。

比如用Semaphore:

semaphore = asyncio.Semaphore(10)

async def fetch_with_limit(url):
    async with semaphore:
        return await fetch(url)

这样最多同时处理10个任务。

我在学校做的“我的珠科小程序”项目的后端其实就是大量爬取学校教务系统、OA系统的各种信息后整合,小程序用户的一个请求→我们后端并发几个请求到学校系统(doge

async函数里别执行长时间同步操作

比如:

@app.get("/test")
async def test():
    time.sleep(10)

    return {"ok": True}

这里虽然函数是:

async def

但:

time.sleep()

仍然是阻塞操作。

它会影响事件循环。

如果确实要执行同步阻塞任务,需要考虑线程池或者其他后台任务方案。

HTTP客户端也需要支持异步

如果FastAPI本身是异步接口,但里面用的是同步HTTP客户端:

requests.get(...)

那网络等待仍然会把当前流程卡住。

如果需要异步请求,可以选支持异步的HTTP客户端。

比如:

import httpx

async with httpx.AsyncClient() as client:
    response = await client.get(url)

这样请求链路就能保持异步。

数据库也一样

如果API用异步数据库驱动,那么:

FastAPI
 ↓
async database
 ↓
await

整个过程更符合异步模型。

但如果:

FastAPI async
 ↓
同步数据库驱动

那异步优势可能会被同步I/O抵消掉。

什么情况下不需要async

并不是所有FastAPI接口都必须写:

async def

如果接口本身:

  • 计算非常简单
  • 没有异步I/O
  • 用同步库
  • 业务逻辑很简单

那普通:

def

也完全够用。

没必要为了"看着现代"把所有代码都改成异步。

我对FastAPI异步的理解

真正值得理解的不是:

async
await

这两个关键字。

而是:

什么时候需要等?
等的时候能不能干别的?
调用链是不是保持异步?
要不要限制并发?

如果只是:

async def

然后里面全是同步阻塞操作,那实际上并没有获得真正的异步收益。

FastAPI的异步能力真正适合的是:

API
 ↓
网络请求
 ↓
数据库
 ↓
Redis
 ↓
第三方服务

这种大量I/O的应用。

理解这一点之后,再去设计FastAPI服务时就不会简单地把"async"当成性能开关,而是会根据实际业务来选择同步还是异步。

最后修改:2026 年 09 月 02 日
如果觉得我的文章对你有用,请随意赞赏