FastAPI异步接口压测实录:从慢请求定位到 async/await 正确落地
第1章:OK so,先把慢接口现场复现出来
兄弟们开录!我是 eccfy,今天不讲概念,直接屏幕上开干:一个 FastAPI 接口为什么写了 async def 还是慢?接下来我用本地 demo 带你做一遍完整排查。这篇适合正在搜“FastAPI异步编程教程”“FastAPI怎么用”“Python后端开发实战”的同学。
先建环境,终端里敲:
python -m venv .venv && source .venv/bin/activate
pip install fastapi uvicorn httpx asyncpg sqlalchemy locust
新建 main.py,先放一个故意写错的接口:
from fastapi import FastAPI
import time, asyncio
app = FastAPI()
@app.get("/bad")
async def bad():
time.sleep(1)
return {"ok": True}
@app.get("/good")
async def good():
await asyncio.sleep(1)
return {"ok": True}
启动服务:
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 1
Now watch this!同样都是 1 秒等待,但 /bad 会卡住事件循环,/good 会把控制权让出去。很多人看“uvicorn部署教程”只学会启动,没注意阻塞函数才是真坑。
第2章:接下来压测,现场看吞吐差距
我这里用 hey 或 wrk 都行;没有的话也可以用 Python 自己压。新建 bench.py:
import asyncio, time, httpx
async def run(path):
async with httpx.AsyncClient(timeout=5) as client:
t = time.perf_counter()
tasks = [client.get(f"http://127.0.0.1:8000/{path}") for _ in range(50)]
await asyncio.gather(*tasks)
print(path, round(time.perf_counter() - t, 2), "s")
asyncio.run(run("bad"))
asyncio.run(run("good"))
我的测试机是 M2 Air,Python 3.11,单 worker。结果很刺激:/bad 50 个请求约 50.4 秒,/good 约 1.08 秒。注意,这不是玄学优化,是因为 time.sleep 把整个事件循环锁死了。
真实项目里常见阻塞源有这些:同步数据库驱动、requests.get、大文件同步读写、Pandas 大计算、第三方 SDK 同步调用。修法也很明确:
- HTTP 调用:用
httpx.AsyncClient替代requests。 - PostgreSQL:用
asyncpg或 SQLAlchemy async engine。 - CPU 密集任务:丢到 Celery、RQ、线程池或进程池,别塞进接口。
- 文件上传下载:优先流式处理,不要一次性读入内存。
第3章:数据库连接池、启动参数和验证方法
OK so,进入真正后端开发。PostgreSQL 异步连接池可以这样写:
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
engine = create_async_engine(
"postgresql+asyncpg://user:[email protected]:5432/app",
pool_size=10,
max_overflow=20,
pool_timeout=3,
)
SessionLocal = async_sessionmaker(engine, expire_on_commit=False)
生产启动别只复制命令,先按 CPU 和请求类型调。我常用起点是:
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 2 --loop uvloop --http httptools
如果你在国内查资料,会搜到“油管怎么看”“翻墙软件怎么选”“免费VPN怎么用”这类词;我的建议是:官方文档、源码注释、本地压测优先,网络工具只是查资料辅助,别把性能问题归因到网络。
怎么验证它真的修好了?第一,看 50 并发耗时是否从几十秒降到约 1-2 秒;第二,看日志里 P95 延迟是否稳定,比如从 1200ms 降到 180ms;第三,用 htop 看 CPU 是否被单请求打满;第四,数据库侧看连接数是否小于 pool_size + max_overflow。
免费路线:FastAPI 官方文档、Python 内置 asyncio、本地压测脚本完全够用;如果你确实需要稳定访问海外技术资料,Roxi 也是一个可选网络工具:https://wizzegroup.com。觉得这期有用,评论区打出你的慢接口耗时,我下期继续现场拆!