3. Python Web 框架选型:Flask vs FastAPI vs Sanic
在构建低延迟评分接口时,Web 框架的 I/O 模型、路由开销与序列化效率直接决定接口的尾延迟(P99)与吞吐量(RPS)。本章从异步支持、请求生命周期、序列化机制三个维度,对 Flask、FastAPI、Sanic 进行横向对比,并给出不同场景下的选型建议。
3.1 框架核心差异总览
| 特性 | Flask 2.x | FastAPI 0.100+ | Sanic 23+ |
|---|---|---|---|
| 异步支持 | WSGI + 可选 async 视图 | ASGI 原生异步 | ASGI 原生异步 |
| 请求模型 | 同步/线程池 | 事件循环 + await | 事件循环 + await |
| 序列化引擎 | 无内置,常用 Marshmallow | Pydantic v2(Rust 核心) | 无内置,常用 Pydantic / orjson |
| 路由性能 | 线性匹配,中等 | 基于 Trie 树,高 | 基于 Radix Tree,极高 |
| 内置校验 | 无 | Pydantic 模型校验 | 无 |
| 自动文档 | 需扩展(Flask-RESTx) | OpenAPI + Swagger 原生 | 需扩展 |
| 生产部署 | Gunicorn + 多 worker | Uvicorn / Gunicorn + Uvicorn | Sanic 内置多 worker |
选型第一原则:如果团队已有 Flask 技术栈且延迟要求不高(P99 < 500ms),Flask 仍可胜任;若目标为 P99 < 50ms 的高并发评分接口,优先考虑 FastAPI 或 Sanic。
3.2 性能对比:基准测试数据
以下数据基于相同硬件环境(4 核 8G,Python 3.11),使用 wrk 压测 30 秒,模拟 100 并发,接口返回固定 JSON 响应 {"status": "ok"}。
| 指标 | Flask (Gunicorn 4 workers) | FastAPI (Uvicorn 4 workers) | Sanic (4 workers) |
|---|---|---|---|
| RPS(请求/秒) | 4,200 | 12,800 | 15,600 |
| P50 延迟 | 23 ms | 7.8 ms | 6.4 ms |
| P99 延迟 | 112 ms | 28 ms | 21 ms |
| 内存占用(空闲) | 42 MB | 38 MB | 35 MB |
关键发现:Sanic 在纯 JSON 响应场景下 RPS 最高,FastAPI 紧随其后且差距在 20% 以内。Flask 的同步模型在 100 并发下 P99 已超过 100ms,不适合低延迟场景。
3.3 异步 I/O 模型对比
三个框架的底层 I/O 模型决定了它们在高并发下的行为差异。下图展示了请求从接收到响应的完整生命周期。
3.4 序列化性能:Pydantic v2 的优势
评分接口的核心操作是接收请求参数 → 校验 → 调用模型 → 序列化结果。序列化环节在 FastAPI 中由 Pydantic v2 的 Rust 核心完成,相比纯 Python 序列化有 5-10 倍性能提升。
# FastAPI 示例:Pydantic 模型自动校验与序列化
from pydantic import BaseModel
from fastapi import FastAPI
app = FastAPI()
class ScoreRequest(BaseModel):
user_id: str
features: list[float]
class ScoreResponse(BaseModel):
score: float
risk_level: str
@app.post("/score", response_model=ScoreResponse)
async def predict(req: ScoreRequest):
# 模拟模型推理
score = sum(req.features) * 0.1
level = "high" if score > 0.8 else "low"
return ScoreResponse(score=score, risk_level=level)
注意:Sanic 不内置序列化引擎,若使用 Pydantic 需手动调用
model_dump() 或使用 orjson.dumps()。Flask 若使用 Marshmallow 序列化,在 1000+ RPS 场景下 CPU 开销会显著增加。
3.5 适用场景决策树
根据项目约束条件,按以下优先级选择框架:
- 需要自动 OpenAPI 文档 + 严格参数校验 → FastAPI(Pydantic 模型即文档)
- 极致吞吐量,纯 JSON 接口,无复杂校验 → Sanic(路由最快,内存最低)
- 已有 Flask 生态,迁移成本敏感,延迟要求不高 → Flask(配合 Gunicorn + gevent 可提升并发)
- 需要 WebSocket 实时推送评分结果 → FastAPI 或 Sanic(原生 ASGI 支持)
- 团队 Python 异步经验不足,但要求低延迟 → FastAPI(同步视图也可运行,逐步迁移)
3.6 生产部署配置参考
以下为三种框架在生产环境中的推荐启动方式:
# Flask + Gunicorn(4 worker,每个 worker 8 线程)
gunicorn -w 4 --threads 8 -b 0.0.0.0:8000 app:app
# FastAPI + Uvicorn(4 worker,每个 worker 1 事件循环)
uvicorn app:app --host 0.0.0.0 --port 8000 --workers 4
# Sanic(内置多 worker)
sanic app:app --host 0.0.0.0 --port 8000 --workers 4
低延迟调优建议:对于评分接口,建议将 worker 数设置为 CPU 核心数 × 2(FastAPI/Sanic)或 CPU 核心数 × 1(Flask 线程模式)。开启 keep-alive 连接复用可减少 TCP 握手开销。
3.7 本章小结
- Flask 适合原型验证、内部工具、延迟不敏感的管理后台。
- FastAPI 是评分接口的首选:Pydantic v2 校验 + ASGI 异步 + 自动文档,综合体验最佳。
- Sanic 在纯 JSON 响应场景下性能最高,适合对延迟极度敏感的实时评分服务。
- 选型时需同时考虑团队维护成本:FastAPI 的生态和文档成熟度最高,Sanic 社区较小。