▶ 重新理解这个问题
我以前是FastAPI至上主义者——不是有毒的那种,是Python开发者终于逃离Node回调地狱或Java样板世界后那种安静的得意:"FastAPI快得惊人,建在Starlette上,异步,是未来。"
直到朋友发来TechEmpower框架基准链接。我点开,期待看到FastAPI坐在榜首嘲笑Django和Flask。结果看到一场屠杀:
原始JSON序列化基准里,Node.js(Express)比FastAPI快2.6x,Go(Gin)快14.8倍。
我盯着屏幕,刷新页面,查日期确认没幻觉。我心爱的类型安全异步FastAPI,被2010年的JS框架和一个看起来像MS Paint设计的Go框架碾碎。
但我做了理性工程师该做的:停止恐慌,打开终端,自己跑测试。
▶ "Hello World"谬误
TechEmpower和多数原始基准测的是框架开销:起一个服务器,用wrk或wrk2打它,测端点什么都不做只返回静态JSON时的每秒请求数(RPS)。
这个场景里无数据库、无认证、无业务逻辑,服务器只做路由+把字典序列化成JSON。
纯真空里Python就是比Go慢:解释型语言+GIL,Go编译成原生机器码+轻量goroutine,Node跑在高度优化的V8上。所以真空里Gin碾FastAPI、Express能赢、Rust的Axum让它像土豆上跑。
但我们不在真空里建应用。
▶ 真实世界测试:I/O是均衡器
真实端点做三件事:从Authorization头验证JWT、查PostgreSQL拿用户资料、把用户对象序列化成JSON返回。
我用FastAPI、Express、Gin各建了这个端点,放同样的AWS c6i.large实例,指同一个PostgreSQL,用wrk打1000并发:
▷ Gin (Go):14,200 RPS
▷ FastAPI (Python):11,800 RPS
▷ Express (Node.js):9,400 RPS
14.8x差距消失了。FastAPI不是慢14.8倍——它比Express快,只比Gin慢约17%。
为什么差距缩得这么狠?因为I/O。应用等数据库查询返回、等外部API网络调用时,CPU完全闲着。
Go用goroutine、Node用事件循环、FastAPI用asyncio——三个处理I/O密集任务都极其高效。语言的原始速度只在CPU真算数时才有意义。而90%的Web应用(CRUD、dashboard、SaaS平台)是I/O密集,不是CPU密集。
真实世界里,FastAPI绝对够快。
▶ 真正罪魁祸首:Pydantic
如果Python的I/O处理与Node和Go持平,为什么原始基准里FastAPI还是慢?
答案不是Python,是Pydantic。
FastAPI用Pydantic做数据验证和序列化。请求进来,Pydantic解析JSON、对照你的类型提示逐字段检查、必要时强转类型、建Python对象;响应出去,反向再来一遍。
这是不可思议的开发者体验:自动OpenAPI文档、类型安全、零样板验证。但它有CPU税。
Express不默认验证你的数据(除非显式加Joi或Zod中间件);Gin要求手动绑定和验证struct。FastAPI自动做——每次请求、默认。
你在为便利付费。问题是税太高吗?
▶ 怎么让FastAPI真快起来
看到原始基准数字心跳加速?别慌,不用重写成Go。四招缩小差距:
▷ 1. 换掉默认JSON编码器——Python内置json库慢,FastAPI默认用它。换成orjson(Rust写的JSON库):
app = FastAPI(default_response_class=ORJSONResponse)
效果:JSON重端点吞吐提升15-20%。
▷ 2. 用uvloop和httptools——Uvicorn默认用Python标准asyncio事件循环和HTTP解析器。换成高度优化的C扩展:
pip install uvloop httptools
uvicorn main:app --loop uvloop --http httptools
效果:原始RPS提升约10%。
▷ 3. Gunicorn多worker跑——FastAPI异步能力限单进程。4核CPU只跑一个Uvicorn worker,3个核完全闲置:
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker
效果:4核机器4倍吞吐。生产环境必做。
▷ 4. 优化Pydantic验证——返回大对象列表时Pydantic序列化是瓶颈。出站不需要严格验证就绕过:
return [user.__dict__ for user in db.query(User).all()]
效果:大payload巨大加速。注意别泄露敏感数据。
▶ 什么时候用什么
▷ 用Gin (Go)——建高吞吐微服务(API网关、实时竞价引擎);负载重度CPU密集;要榨干硬件最后一滴性能省云账单;不介意样板和更严格的类型系统。
▷ 用Express (Node.js)——前端是React/Next.js想前后端共享类型和逻辑;要快速原型和npm生态;应用大部分I/O密集、重视开发速度胜过原始RPS。
▷ 用FastAPI——建数据重应用、ML管道、AI集成(Python在这里是无可争议的王者);要零配置的自动交互API文档(Swagger UI);重视开箱即用的类型安全和数据验证;要Python生态最好的开发者体验。
▶ 我的发现
FastAPI够快吗?
建下一代高频交易平台(微秒值几百万美元)?不够,用C++或Rust。
建SaaS平台、数据dashboard、每秒几千请求的API?够,绰绰有余。
最认可一句:14.8x差距是基准伪影——它测的是引擎的速度,不是车的速度。真实世界里数据库、网络、外部API决定节奏,FastAPI跟得正好。
判断:别担心基准,担心你的数据库索引——慢数据库杀应用比Python快得多。我自己的生产经验验证了I/O均衡器效应:JWT验证+DB查询的端点,三框架差距从14.8x缩到1.2x以内。
先换orjson和uvloop,加Gunicorn多worker——十分钟改动,收益立竿见影。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.