别学我!这是反面教材
FastAPI真香,但别被它骗了
上周五晚上九点半,我瘫在工位上刷知乎,突然收到leader微信:“下周三前搞个内部工具的后端接口,用 FastAPI 吧,轻量快。”
我盯着消息愣了三秒——入职新公司才俩月,天天摸鱼看开源项目源码(主要是 Rust 和 Go 的区块链相关库,别问,问就是“技术前瞻性”),结果第一次正经写业务代码就被扔进火坑?更离谱的是,我们组主语言明明是 Java,现在却让我这个 Python 新手去搭后端……产品经理还在群里@我说“要支持未来对接链上数据”,我差点一口老血喷在键盘上。
但没办法,deadline 就像达摩克利斯之剑。好在我之前在家折腾过 Flask 和 Django,对 Python web 框架不算完全小白。抱着“反正能跑就行”的佛系心态,我决定试试最近风很大的 FastAPI。
为什么不是 Java?也不是 Node?
先说清楚背景:我们团队主力是 Java,Spring Boot + MyBatis 那套玩得飞起。但这次是个临时内部工具,需求模糊、迭代快、没人愿意花时间搭完整微服务架构。运维大哥一听又要开新服务就皱眉:“又是 Java?JVM 内存占得比我还高!”
而我私下其实一直觉得,Python 在快速原型开发上真的香。特别是 FastAPI,号称“高性能”,还自动生成 Swagger 文档——对我们这种连 API 文档都要手动写的穷团队来说,简直是救星。
至于 Node?前端同事倒是推荐过 Express,但我对回调地狱有 PTSD,而且这次要对接一些链上合约读取逻辑(虽然只是模拟),Python 的 Web3.py 库比 JS 版本稳定多了(至少在我试用时没崩)。
所以,FastAPI 成了折中选择:轻量、快、文档自动生成、类型安全,还能用 async/await 玩点异步操作——万一以后真要接区块链节点呢?
安装?一行命令搞定,但别高兴太早
pip install fastapi uvicorn[standard]
官方文档写得贼简单,uvicorn main:app --reload 跑起来,localhost:8000/docs 直接弹出交互式 Swagger UI。那一刻我真的感动了——对比以前在 Spring Boot 里配 SwaggerConfig 配到怀疑人生,FastAPI 真的是“开箱即用”。
但问题很快就来了。
我们这工具需要连接数据库(MySQL),还要支持未来可能的链上数据查询。我一开始直接在全局 scope 里初始化数据库连接:
from sqlalchemy import create_engine
engine = create_engine("mysql://...")
结果一压测,连接池爆了。运维小哥在 Slack 里幽幽地说:“兄弟,你这每个请求都新建连接?我们 DBA 要报警了。”
后来改用 databases + asyncmy 异步驱动,配合依赖注入管理连接生命周期,才算稳住。这里特别提醒:FastAPI 虽然支持 async,但你的数据库驱动也得跟上。用同步库(比如 pymysql)在 async 函数里?等着阻塞整个 event loop 吧。
接口设计:别让产品经理毁了你的 API
需求文档只有三行字:“用户能上传文件、查看历史记录、导出成 CSV”。听起来简单,但实际开发时产品经理又加了一堆“小需求”:
- “能不能加个状态字段?比如‘处理中’、‘已上链’?”
- “导出的时候要包含交易哈希!”
- “哦对了,权限控制也要有,不同部门只能看自己的”
我当时就想翻白眼。但转念一想,这不正好练手 FastAPI 的 Pydantic 模型和依赖注入吗?
于是,我定义了清晰的 DTO:
from pydantic import BaseModel, Field
from typing import Optional
class UploadRequest(BaseModel):
file_name: str = Field(..., max_length=100)
department: str = Field(..., pattern=r"^[A-Z]{2,5}$") # 部门代码必须是大写字母
class RecordResponse(BaseModel):
id: int
file_name: str
status: str # "pending", "on_chain", "failed"
tx_hash: Optional[str] = None # 区块链交易哈希,可为空
created_at: datetime
Pydantic 自动校验字段,非法请求直接 422,省了我一堆 if-else。而且配合 OpenAPI 自动生成文档,前端同事看了一眼就说:“哟,字段说明都有,不用问你了。” —— 这是我今天最开心的时刻。
至于权限控制?FastAPI 的 Depends 太好用了:
async def get_current_user(token: str = Header(...)):
if token not in VALID_TOKENS:
raise HTTPException(status_code=403, detail="Invalid token")
return decode_token(token)
@app.get("/records")
async def get_records(user: dict = Depends(get_current_user)):
# 只返回 user['dept'] 对应的数据
...
一行注解,权限逻辑抽离干净。对比我在 Java 项目里写 AOP + 注解 + 拦截器那一套,简直降维打击。
区块链?别被 buzzword 带偏节奏
说到“对接区块链”,其实现阶段只是模拟。但我们还是预留了接口扩展性。比如,当文件处理完成后,调用一个 publish_to_chain() 函数,返回 transaction hash。
关键在于:别把区块链当银弹。很多新人一听到“区块链”就以为要重写整个后端,其实大多数场景下,它只是另一个外部服务——就像调用支付网关一样。
我在代码里抽象了一个 ChainClient:
class ChainClient:
async def publish(self, data: dict) -> str:
# 模拟发交易,实际可能是调用 Infura 或自建节点
await asyncio.sleep(1) # 模拟网络延迟
return "0x" + os.urandom(32).hex()
然后通过依赖注入传入路由:
@app.post("/upload")
async def upload_file(
req: UploadRequest,
chain: ChainClient = Depends(get_chain_client)
):
# ... 保存文件
tx_hash = await chain.publish({"file": req.file_name})
return {"status": "on_chain", "tx_hash": tx_hash}
这样,未来真要换 Web3.py 或 ethers.py,只要改 ChainClient 实现就行。后端的核心永远是业务逻辑和数据流,不是技术名词堆砌。
性能与部署:别在本地爽完就交差
FastAPI 官方吹性能接近 Go,但那是在理想条件下。我本地测试 QPS 2000+,但一上公司测试环境,直接掉到 300。排查半天,发现是数据库连接没复用,加上中间有个同步函数偷偷阻塞了事件循环。
最终优化点:
- 使用
asyncmy替代pymysql - 所有 I/O 操作(包括文件读写、HTTP 请求)都改造成 async
- 用
gunicorn + uvicorn.workers.UvicornWorker启动多进程
部署脚本长这样:
gunicorn -k uvicorn.workers.UvicornWorker \
-w 4 \
--bind 0.0.0.0:8000 \
--timeout 60 \
main:app
运维大哥看了直呼内行:“总算不像 Flask 那样单线程裸奔了。”
另外,我们加了 Prometheus 指标埋点(用 prometheus-fastapi-instrumentator),监控请求延迟和错误率。上线三天,零故障——虽然功能简单,但稳定性比隔壁 Java 服务还好(笑)。
和 Java 后端比,FastAPI 适合什么?
有人问我:“既然你们主栈是 Java,为啥不统一技术栈?”
我的回答是:看场景。
| 维度 | Java (Spring Boot) | FastAPI |
|---|---|---|
| 启动速度 | 慢(JVM 预热) | 快(秒级) |
| 内存占用 | 高(通常 >500MB) | 低(<100MB) |
| 开发效率 | 中(配置多) | 高(自动文档、类型校验) |
| 团队熟悉度 | 高 | 低(需学习) |
| 适合场景 | 核心业务、高并发、复杂事务 | 工具类、MVP、数据管道、AI 服务 |
对我们这种“临时内部工具 + 未来可能接链”的模糊需求,FastAPI 的敏捷性碾压 Java。但如果要做金融级交易系统?我第一个举手投 Java。
写在最后:躺平,但别躺废
说实话,这次任务让我重新审视了“技术选型”这件事。以前总想着“用最酷的框架”,但现在觉得,能快速解决问题、维护成本低、团队能接手,才是王道。
FastAPI 让我两周内交付了一个可用、可测、可监控的后端服务,还顺手学了 async/await 和依赖注入的最佳实践。虽然平时我还是喜欢摸鱼看比特币源码,但该干活时,也得拿出点真本事。
毕竟,老板不会因为你研究了三天 Ethereum 的默克尔树就给你涨工资——但他可能会因为你三天搞定一个工具而少骂你几句。
所以啊,程序员可以佛系,但代码不能糊弄。FastAPI 是个好工具,但别被它的“简单”迷惑——背后的设计哲学、异步模型、类型安全,才是真正值得深挖的。
下次再有人说“Python 不适合后端”,我就把这篇甩他脸上。
(完)
P.S. 上周上线后,产品经理又提了个需求:“能不能加个 AI 自动分类?”……我默默打开了 Hugging Face 的文档。

评论 0