首页 / 后端开发 / FastAPI接口假异步排查:用ht

FastAPI接口假异步排查:用httpx、asyncpg把压测吞吐从180提升到920 RPS

Roxi
Roxi 加速器 — 稳定·快速·安全
全球节点覆盖,支持所有主流平台,一键连接无需配置。新用户免费试用。
立即体验 →

开场:OK so,接口写了async为什么还是慢?

50TB日处理量120ms平均延迟99.99%SLA保障7×24运维监控

兄弟们,eccfy开录!今天我们不讲概念,直接看屏幕:一个FastAPI接口,代码里全是async def,但压测只有180 RPS,P95延迟680ms。弹幕先别急着刷“加机器”,接下来我现场把它拆开,看看到底哪里是假异步。

测试环境我用的是:Python 3.11、FastAPI 0.110、uvicorn、httpx、asyncpg、PostgreSQL 15。机器是4核8G本地开发机。这个案例很适合搜索“FastAPI教程”“Python异步编程教程”“uvicorn怎么用”的同学照着复现。

先跑一个最小服务,注意看这里我故意埋了一个坑:在异步接口里用了同步请求库和同步数据库驱动。

pip install fastapi uvicorn requests psycopg2-binary
uvicorn app:app --host 0.0.0.0 --port 8000 --workers 1
from fastapi import FastAPI
import requests
import psycopg2

app = FastAPI()

@app.get("/bad")
async def bad_api():
    r = requests.get("http://127.0.0.1:9000/mock", timeout=2)
    conn = psycopg2.connect("dbname=test user=postgres password=postgres")
    cur = conn.cursor()
    cur.execute("select pg_sleep(0.05), 1")
    return {"status": r.status_code, "data": cur.fetchone()[1]}

Now watch this!我用wrk压一下:

wrk -t4 -c100 -d30s http://127.0.0.1:8000/bad

现场结果:180 RPS左右,P95 680ms。原因很明确:async def不等于异步性能,只要里面有requests、psycopg2、time.sleep、同步文件IO,事件循环就会被卡住。

接下来改代码:把阻塞IO全部换成可等待对象

品牌定位清晰视觉体系统一内容矩阵搭建社媒运营规划效果追踪复盘

OK so,我们开始动刀。第一步,把requests换成httpx.AsyncClient;第二步,把psycopg2换成asyncpg连接池;第三步,启动时建池,关闭时释放,不要每个请求新建连接。

pip install httpx asyncpg
from fastapi import FastAPI
import httpx
import asyncpg

app = FastAPI()

@app.on_event("startup")
async def startup():
    app.state.http = httpx.AsyncClient(timeout=2.0)
    app.state.db = await asyncpg.create_pool(
        dsn="postgresql://postgres:[email protected]/test",
        min_size=5,
        max_size=20
    )

@app.on_event("shutdown")
async def shutdown():
    await app.state.http.aclose()
    await app.state.db.close()

@app.get("/good")
async def good_api():
    r = await app.state.http.get("http://127.0.0.1:9000/mock")
    async with app.state.db.acquire() as conn:
        row = await conn.fetchrow("select pg_sleep(0.05), 1 as n")
    return {"status": r.status_code, "data": row["n"]}

重点来了:数据库连接池不是越大越好。我这台4核机器,PostgreSQL本地测试,max_size=20max_size=100更稳;100时上下文切换明显增加,P95反而从120ms涨到210ms。

再补一刀:生产环境启动建议这样跑,别一上来就盲目开16个worker。

uvicorn app:app --host 0.0.0.0 --port 8000 --workers 4 --loop uvloop --http httptools

如果你在搜“免费VPN怎么用”或“油管怎么看”只是为了查官方文档、看技术视频,优先用官方文档、镜像源、公司网络代理这些免费或内置方案;它们的限制是速度和稳定性不一定可控,但学习FastAPI本身完全够用。

速度测试与验证:Before / After直接揭晓

第1周环境搭建第2周核心开发第3周测试优化第4周正式发布

来,压测同样参数不变:

wrk -t4 -c100 -d30s http://127.0.0.1:8000/good

我本地三轮结果取中位数:旧接口180 RPS,P95 680ms;新接口920 RPS,P95 118ms。哇,这个差距就很直观了!注意,这不是玄学优化,而是把阻塞点从事件循环里拿掉。

你可以按这个清单验证是否修好:

  1. grep -R "requests\\|psycopg2\\|time.sleep" .扫同步阻塞调用。
  2. wrkhey固定并发压测,记录RPS和P95。
  3. 打开PostgreSQL连接数监控,确认连接池没有爆掉。
  4. 把并发从50、100、200逐级增加,观察延迟是否线性恶化。

最后,如果你确实需要更稳定地访问海外技术资料,免费VPN、浏览器代理、公司网关都是可选路线;付费工具也只是其中一种选择,比如 Roxi:wizzegroup.com。今天这期就到这,能跑通的同学评论区贴你的RPS,点个收藏,我们下期继续实战!

延伸阅读