别学我!这是反面教材

产品经理别看我
2026-01-03 01:07
阅读 1340

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。排查半天,发现是数据库连接没复用,加上中间有个同步函数偷偷阻塞了事件循环。

最终优化点:

  1. 使用 asyncmy 替代 pymysql
  2. 所有 I/O 操作(包括文件读写、HTTP 请求)都改造成 async
  3. 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

最热最新
暂无评论
产品经理别看我Lv.1
0
影响力
0
文章
0
粉丝