FastAPI 入门:被 Go 和 SpringBoot 包围的 Python 新人自救指南

LeetCode逃兵
2026-01-14 08:42
阅读 475

上周五晚上十点半,我盯着 MacBook 屏幕上疯狂报错的日志,一边啃着冷掉的泡面,一边怀疑自己是不是真的不适合写后端。刚入职两周,试用期还没过半,就被分配了一个“简单”的任务:用公司新选型的框架搭一个内部数据同步服务。老板说:“你不是会 Python 吗?试试 FastAPI,轻量、快、文档自动生成,很适合你这种新人上手。”

我心想,不就是个 API 框架嘛,能有多难?结果三天过去,连本地测试都没跑通——因为隔壁组用的是 Go 写微服务,后端老大哥们开会时张口闭口“goroutine”“context cancel”,而 Java 组还在炫耀他们 SpringBoot 3.x 的响应式编程。我这个拿着 Python 偷偷在家撸代码的远程新人,瞬间感觉自己像个格格不入的异类。

但没办法,deadline 就在下周三,产品经理已经发了三次提醒邮件(附带可爱表情包,杀伤力翻倍)。于是,我咬咬牙,把 Windows 虚拟机关掉(只留着测兼容性),打开 VS Code + iTerm2,在 Mac 上开启了 FastAPI 的血泪入门之路。


为什么是 FastAPI?而不是 Go 或 SpringBoot?

说实话,我一度想偷偷用 Flask 糊弄过去。毕竟 Flask 我熟啊!但团队技术栈评审会上,架构师甩出一张性能对比图:

框架 并发吞吐 (req/s) 自动文档 类型安全 学习曲线
Flask ~1,200
Django REST ~900 ✅(需插件) ⚠️ ⭐⭐⭐
FastAPI ~18,000 ⭐⭐
SpringBoot ~15,000 ✅(Swagger) ⭐⭐⭐⭐
Go (Gin) ~30,000+ ❌(需手写) ⭐⭐⭐

看到没?FastAPI 在 Python 生态里几乎是性能天花板,还自带 OpenAPI 文档和 Pydantic 强类型校验。老板一句话总结:“我们要快速迭代,又要保证接口规范,Go 太重,SpringBoot 团队没人会,你就上 FastAPI 吧。”

行吧,我认了。


第一个坑:你以为装完就能跑?

pip install fastapi uvicorn

然后写了个 hello world:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

运行 uvicorn main:app --reload,浏览器一开——404?!

我当场懵了。查了半天才发现,Mac 上的 Python 环境被我之前玩 Jupyter 时搞乱了,系统默认的 pip 装到了全局,而项目用的是 pyenv 的虚拟环境。教训一:永远用 python -m pip 而不是直接 pip

更惨的是,第二天晨会演示时,我忘了加 --host 0.0.0.0,结果同事访问我的内网 IP 直接 timeout。运维大哥幽幽来了一句:“你这服务只监听 localhost 啊?” 我脸都红了。

正确启动姿势:

uvicorn main:app --host 0.0.0.0 --port 8000 --reload

--reload 是开发神器,改代码自动重启;但千万别在生产环境用!我们后来上线时就因为忘了关它,导致 CPU 占满,被监控告警炸醒。


类型系统:Pydantic 救我狗命

以前写 Flask,参数校验全靠 request.args.get() + 手动 try-except,经常因为前端传了个字符串 "null" 导致后端崩掉。这次我决定认真对待类型。

FastAPI 默认集成 Pydantic,你可以这样定义请求体:

from pydantic import BaseModel
from fastapi import FastAPI

class SyncRequest(BaseModel):
    source_id: str
    target_env: str
    force_update: bool = False  # 默认值
    batch_size: int = 100

app = FastAPI()

@app.post("/sync")
def trigger_sync(req: SyncRequest):
    # req 已经是强类型对象!
    if req.batch_size > 1000:
        raise HTTPException(status_code=400, detail="Batch too large!")
    return {"status": "queued", "batch": req.batch_size}

神奇的是,只要你 POST 一个 JSON,比如:

{"source_id": "db-01", "target_env": "staging"}

FastAPI 会自动校验字段是否存在、类型是否匹配、默认值是否生效。如果前端传了 batch_size: "abc",直接返回 422 错误,附带清晰的错误路径:

{
  "detail": [
    {
      "loc": ["body", "batch_size"],
      "msg": "value is not a valid integer",
      "type": "type_error.integer"
    }
  ]
}

这体验,简直比 SpringBoot 的 @Valid 还爽——不用写一堆注解,类型即契约。


异步?别被吓到,其实很简单

我们这个同步服务需要调外部 API,还要写数据库。如果用 Flask,要么用线程池,要么等死。但 FastAPI 原生支持 async/await,配合 httpxasyncpg,轻松实现高并发 I/O。

比如调第三方服务:

import httpx
from fastapy import BackgroundTasks

async def fetch_external_data(url: str) -> dict:
    async with httpx.AsyncClient() as client:
        resp = await client.get(url)
        resp.raise_for_status()
        return resp.json()

@app.get("/data")
async def get_data():
    data = await fetch_external_data("https://api.example.com/v1/data")
    return data

注意:不是所有操作都要 async。如果你用的是 SQLite 或普通 pymysql,强行加 async 反而会变慢。我们踩过坑——把数据库换成 PostgreSQL + asyncpg 之后,并发才真正起飞。


文档自动生成:前端同事终于不烦我了

以前每次改接口,都要手动更新 Swagger 或写文档给前端。现在?只要代码一写,文档自动就有了。

访问 http://localhost:8000/docs,你会看到:

  • 所有接口列表
  • 请求/响应示例
  • 可直接在页面测试(带认证)
  • 自动根据 Pydantic 模型生成 Schema

前端小哥第一次看到时惊呼:“这玩意儿是魔法吗?” 产品经理甚至开始用这个页面做需求评审——再也不用等我写 Word 文档了。

而且,你还能加描述:

@app.post("/sync", summary="触发数据同步", description="从 source_id 同步到目标环境")
def trigger_sync(req: SyncRequest):
    ...

文档立刻变得专业起来。对比 SpringBoot 需要额外集成 SpringDoc,Go 更是要手写 OpenAPI 注解,FastAPI 的开箱即用真的香。


生产部署:别再用 uvicorn --reload 了!

开发爽完了,该上线了。我们一开始图省事,直接 nohup uvicorn ... & 丢服务器上,结果半夜被 PagerDuty 告警叫醒——服务挂了。

正确的做法是用 Gunicorn + Uvicorn Worker:

pip install gunicorn uvicorn[standard]

然后写个 gunicorn.conf.py

# gunicorn.conf.py
bind = "0.0.0.0:8000"
workers = 4  # CPU 核数 * 2 + 1
worker_class = "uvicorn.workers.UvicornWorker"
timeout = 60
keepalive = 5

启动命令:

gunicorn -c gunicorn.conf.py main:app

这样才有进程管理、负载均衡、超时控制。我们还配了 Nginx 做反向代理 + SSL,日志统一收集到 ELK。虽然比 Flask 复杂点,但稳定性提升巨大。


和 Go / SpringBoot 的真实差距在哪?

用了两周 FastAPI,我终于理解为什么团队没选 Go 或 SpringBoot:

  • Go:性能确实猛,但开发速度慢。我们这个服务逻辑简单,用 Go 要写 struct、handler、router、middleware 分离,代码量翻倍。而且团队没人会 Go,维护成本高。
  • SpringBoot:生态无敌,但启动慢、内存吃得多。我们这服务只需要几百 MB 内存,Java 动不动 1G+,云账单受不了。
  • FastAPI:在“够快”和“够快开发”之间找到了平衡点。Python 的胶水能力 + 异步支持 + 自动生成文档,特别适合内部工具、中台服务。

当然,如果要做超高并发核心交易系统,我还是会投 Go 一票。但在 90% 的业务场景下,FastAPI 完全够用,甚至更优。


写在最后:试用期新人的感悟

现在,我的数据同步服务已经稳定运行一周,每天处理 50W+ 请求,P99 延迟 < 200ms。上周五复盘会上,后端老大拍了拍我肩膀:“不错啊,FastAPI 用得挺溜。”

其实哪有什么天赋,不过是踩坑踩得多罢了。从环境配置到异步陷阱,从文档缺失到部署翻车,每一步都是血泪教训。但 FastAPI 的设计哲学让我相信:好的框架,应该让开发者专注业务,而不是和工具打架

如果你也是刚入行的 Python 新人,被 Go 和 Java 的光环压得喘不过气,别慌。FastAPI 就是你的秘密武器——它可能不是最快的,但绝对是最友好的。

对了,今天早上产品经理又发来新需求:“能不能加个 WebSocket 实时推送?”
我笑了笑,打开文档,输入 from fastapi import WebSocket……

这一次,我知道该怎么做了。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝