FastAPI入门:Python后端开发新手指南

服务器打盹
2025-12-12 21:08
阅读 318

上周五晚上十一点半,我刚在新公司提交完一个紧急需求的代码,顺手点开招聘网站看了眼——果然又有一堆JD写着“熟悉FastAPI优先”。我苦笑一下,摸了摸咖啡杯底残留的冰块。这已经是我入职新公司的第二个月了,从滴滴干了四年司机端核心业务的老油条,突然切换到一家创业公司搞新项目,技术栈大换血不说,连写接口都得重新学怎么“优雅”。

其实我在滴滴那会儿,主力是Go + Gin,偶尔用Flask搭个内部工具。FastAPI?听说过,但总觉得“不就是个Python框架嘛,能有啥不一样?”直到上个月产品提了个需求:要三天内上线一个司机行为分析的对外API服务,要求高并发、低延迟、还得自动生成文档给合作方调用。我第一反应是:“完了,又要熬夜。” 但转念一想,不如趁机把FastAPI啃下来?

为什么是 FastAPI?不是 Flask/Django?

说实话,一开始我是抗拒的。毕竟在滴滴,我们对性能抠得特别细——双11那种高峰日,司机端每秒几万请求,一个慢查询就能让整个调度系统抖三抖。Python 在我印象里,一直是“脚本语言”,写工具还行,扛生产流量?心里打鼓。

但现实逼人。团队人少、deadline紧、合作方又催着要 OpenAPI 文档。我翻了翻 FastAPI 的文档,发现它有几个点直接戳中痛点:

  • 自动 OpenAPI/Swagger UI:不用手动维护接口文档,对接第三方省下至少两天沟通成本
  • Pydantic 模型校验:参数校验再也不用手写 if-else 堆成山
  • 异步支持(async/await):配合 Uvicorn,理论上能扛住比 Flask 高好几倍的 QPS
  • 类型提示原生支持:作为被 Go 惯坏的人,看到 def create_driver(data: DriverCreate) -> DriverResponse 这种签名简直热泪盈眶

小声吐槽:产品经理上次说“这个接口很简单,就传个ID查个状态”,结果上线后发现没做限流,差点把数据库干趴。现在有了 Pydantic + FastAPI 的自动校验,至少烂参数进不到业务逻辑层——运维兄弟应该会感谢我。

踩坑实录:从“Hello World”到线上跑稳

刚开始写 demo 的时候,一切都很美好:

from fastapi import FastAPI

app = FastAPI()

@app.get("/drivers/{driver_id}")
def get_driver(driver_id: int):
    return {"driver_id": driver_id, "name": "张师傅"}

跑起来,访问 /docs,Swagger UI 自动出来,还能在线调试。我当时心想:“这不比 Flask 香?”

但很快现实就教我做人。

坑1:异步不是万能的,尤其当你连数据库驱动都没切对

我兴冲冲地把 PostgreSQL 查询写成 async:

import asyncio
import asyncpg

@app.get("/drivers/{driver_id}")
async def get_driver(driver_id: int):
    conn = await asyncpg.connect("postgresql://...")
    row = await conn.fetchrow("SELECT * FROM drivers WHERE id = $1", driver_id)
    await conn.close()
    return row

本地测试没问题。但压测一上,QPS 卡在 200 不动。我盯着监控看了半小时,终于意识到:每次请求都新建数据库连接?这不是自杀吗!

赶紧换成连接池:

from databases import Database

database = Database("postgresql+asyncpg://...")

@app.on_event("startup")
async def startup():
    await database.connect()

@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()

@app.get("/drivers/{driver_id}")
async def get_driver(driver_id: int):
    query = "SELECT * FROM drivers WHERE id = :driver_id"
    return await database.fetch_one(query, values={"driver_id": driver_id})

QPS 直接飙到 1500+。那一刻我深刻理解了什么叫“异步只是手段,资源复用才是王道”。

坑2:Pydantic 模型别乱继承,小心序列化爆炸

为了复用字段,我搞了个基类:

class BaseModel(BaseModel):
    id: int
    created_at: datetime

class Driver(BaseModel):
    name: str
    phone: str

结果返回 JSON 时,created_at 变成了 {} —— 因为 Pydantic 默认不处理 datetime 序列化!查了半天文档才发现要加配置:

class Config:
    json_encoders = {datetime: lambda v: v.isoformat()}

或者更简单:直接用 .model_dump() 替代 dict(model)

这种细节,在面试题里可能就是一句“Pydantic 如何处理非 JSON 原生类型?”,但在生产环境,可能就是半夜三点被 PagerDuty 叫醒的原因。

架构设计思考:别只顾着写接口

在滴滴那会儿,我们有个铁律:任何新服务上线前,必须回答三个问题

  1. 流量来了怎么办?(扩缩容)
  2. 接口挂了怎么办?(熔断降级)
  3. 数据错了怎么办?(可追溯)

FastAPI 虽然快,但不代表你可以忽略架构。

我做了几件事:

  • 中间件统一处理日志和 trace_id:方便链路追踪
  • 用 Redis 做缓存穿透保护:司机信息查不到也设个空值,避免 DB 被击穿
  • 接口加 rate limit:用 slowapi 包,按 IP 限流
  • 健康检查接口:K8s 就靠它判断 pod 是否 ready
from fastapi import Request
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address

limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

@app.get("/drivers/{driver_id}")
@limiter.limit("100/minute")
async def get_driver(request: Request, driver_id: int):
    # ...

上线一周,没出 P0 事故。运维大哥终于没在群里@我了,感动。

性能对比:FastAPI 到底快多少?

闲着无聊,我拿 Flask 和 FastAPI 同样逻辑压测了下(Uvicorn vs Gunicorn+Gevent):

框架 并发 100 QPS 平均延迟
Flask 100 320 312ms
FastAPI (sync) 100 480 208ms
FastAPI (async) 100 1650 60ms

数据仅供参考,但结论很明显:如果你的 I/O 密集(比如查 DB、调外部 API),异步 FastAPI 能榨干机器性能。不过要注意,CPU 密集型任务(比如图像处理)还是扔给 Celery 或者直接用 Go 更合适。

开发心得 & 给新人的建议

作为一个从“老派后端”转型的人,我的真心话:

  • 别被“快”迷惑:FastAPI 快,但你的 SQL 慢,照样拉胯。记得 explain 你的查询。
  • 善用依赖注入Depends() 看似花哨,但解耦数据库、权限、上下文超有用。
  • 测试不能省:FastAPI 官方推荐用 TestClient,写单元测试比 Flask 顺手太多。
  • 别在 main.py 写业务:分层!models / schemas / crud / api / core,该拆就拆。

至于面试题挑战?最近面了几个候选人,问“FastAPI 为什么快”,有人答“因为用了 Starlette”,这没错,但更深层的是:基于 ASGI 的异步模型 + Pydantic 的 C 扩展加速 + 类型提示带来的编译期优化。能聊到这层,基本就过了。

结语

写这篇文章的时候,已经是凌晨两点。窗外北京的夜很安静,只有键盘咔嗒声。回想这两个月,从抗拒到真香,FastAPI 确实让我重新爱上了 Python 后端开发——不是因为它多炫酷,而是它在保持 Python 简洁的同时,给了你接近 Go 的工程能力

如果你也是刚入行的 Python 新手,或者像我一样从别的语言转过来,不妨试试 FastAPI。它可能不会让你一夜暴富,但至少能让你在 deadline 前睡个好觉(大概)。

对了,刚收到产品消息:“下周要加个实时位置推送接口……”
算了,不说了,我去研究 WebSocket 了。

评论 0

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