FastAPI入门:用Python打造高性能后端服务的实战记录

罗思宇◇
2025-06-21 13:54
阅读 396

开篇:我为什么要选FastAPI做项目?

开篇:我为什么要选FastAPI做项目?

去年,我在一家初创公司负责一个内部系统的重构工作。这个系统原本是用Flask搭起来的,主要功能是对接多个外部业务系统进行数据聚合、处理和展示。随着用户数量的增长和接口调用量的上升,老系统开始频繁出现响应慢、并发瓶颈等问题。

在一次性能压力测试中,当并发请求数达到80时,CPU已经接近饱和,TP99延迟超过2秒。我们团队一致认为必须对后端架构进行一次彻底改造。

当时,我们在技术选型上考虑过几种方案,比如Node.js、Golang和基于Python的新框架。最终,出于团队的技术栈沉淀(都是Python背景)和项目迭代速度的要求,我选择了FastAPI。这是我第一次将它正式用于生产项目,但这次尝试让我彻底改观了对Python后端能力的看法。


问题描述:传统Flask框架在高并发下的痛点

问题描述:传统Flask框架在高并发下的痛点

原系统存在几个比较明显的问题:

  1. 单线程模式导致性能瓶颈严重

    • Flask默认使用Werkzeug开发服务器,本质上还是同步阻塞式模型
    • 接口处理过程中一旦涉及数据库操作或第三方服务调用,整个请求就被卡住
  2. 缺乏自动文档生成机制

    • 接口文档靠人工维护,更新滞后严重,影响前后端协作效率
  3. 代码结构混乱

    • 没有良好的工程化组织方式,很多业务逻辑直接写在路由函数里
  4. 异常处理不统一

    • 各种接口抛出的错误码五花八门,前端难以统一处理

这些问题严重影响了系统的稳定性、可维护性和扩展性。我们需要一个既能快速迭代,又能扛得住压力的解决方案。


解决方案:为什么选择FastAPI?

解决方案:为什么选择FastAPI?

FastAPI的优势其实很多人已经耳熟能详,但我更想结合我的实际项目经验来聊聊它是怎么帮我们解决具体问题的。

✅ 异步支持开箱即用

FastAPI底层依赖Starlette,天生具备异步IO的支持。这对于大量需要等待网络请求或数据库查询的接口来说至关重要。我们只需要简单修改部分数据库查询为async函数,就能有效释放线程资源。

✅ 类型注解+自动生成OpenAPI文档

这点简直救了我。过去每次改完一个接口都要手动更新Swagger文档,经常忘记。现在只要给参数加上类型声明,文档就自动更新好了,而且UI非常友好。

@app.get("/users/{user_id}", response_model=UserResponse)
def read_user(user_id: int, q: Optional[str] = None):
    ...

✅ 高性能表现惊人

在重构完成后,我们再次压测,在同等配置下,吞吐量提升将近三倍,TP99稳定在300ms以内。这超出了我们的预期。

小插曲:上线前测试环境部署时误用了uvicorn.run(...)而不是--host启动方式,后来发现性能差很多。所以别小看部署方式的选择,后面我会专门讲踩坑点。


代码实践:从零搭建一个简单的API服务

代码实践:从零搭建一个简单的API服务

下面我带大家一步步实现一个简化版的项目示例——“用户信息中心”。这个服务会提供基础的用户信息增删查改,并模拟调用下游系统获取额外数据。

🧱 工程目录结构

这是我们项目的典型结构:

my_fastapi_project/
├── app/
│   ├── __init__.py
│   ├── main.py
│   ├── api/
│   │   └── users.py
│   ├── models/
│   │   └── user.py
│   ├── schemas/
│   │   └── user.py
│   └── database.py
├── requirements.txt
└── config.yaml

🔌 初始化项目

pip install fastapi uvicorn
uvicorn app.main:app --reload

💬 定义接口:用户列表接口

# app/api/users.py
from fastapi import APIRouter
from typing import List
from ..models.user import UserInDB
from ..schemas.user import UserCreate, UserUpdate, UserResponse

router = APIRouter()

@router.get("/users", response_model=List[UserResponse])
def get_users(skip: int = 0, limit: int = 10):
    # 假设这里是从数据库取的数据
    fake_users_db = [
        {"id": 1, "name": "Tom", "email": "tom@example.com"},
        {"id": 2, "name": "Jerry", "email": "jerry@example.com"}
    ]
    return fake_users_db[skip: skip + limit]

然后在main.py注册路由模块:

from fastapi import FastAPI
from app.api.users import router as users_router

app = FastAPI()
app.include_router(users_router)

这样,当我们访问 /docs 的时候就能看到自动生成的接口文档了!


踩坑经验:那些年我遇到的大大小小的坑

FastAPI虽好,但在实际使用中也不是没有坑,特别是第一次用于生产项目的时候。

❗ 数据库连接池配置不当

一开始我们使用的是普通的SQLAlchemy连接,结果在并发高的时候经常报错 QueuePool limit of size 5 overflow 10 reached

后来我们改成了 sqlalchemy.ext.asyncio.AsyncSession + asyncpg,配合连接池配置才解决这个问题。

from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker

engine = create_async_engine(
    settings.DATABASE_URL,
    pool_pre_ping=True,
    pool_size=20,
    max_overflow=10
)

AsyncSessionLocal = sessionmaker(
    bind=engine,
    class_=AsyncSession,
    expire_on_commit=False
)

❗ 跨域设置容易遗漏

刚开始我们没注意CORS的设置,前端一直报错跨域问题。FastAPI提供了中间件可以快速解决:

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

建议不要直接放行所有域名,可以根据环境配置允许的域名列表。

❗ 日志输出格式混乱

日志这块我们走了弯路。早期为了图方便,直接print调试信息,结果线上日志完全没法追踪。

后来我们采用了标准logging模块,并接入ELK日志系统,结构化输出日志内容,排查问题效率大大提升。

import logging
from fastapi.logger import logger

logging.basicConfig(level=logging.INFO)
logger.setLevel(logging.INFO)

效果总结:重构后的收益有多大?

重构完成后,我们将新旧系统做了对比测试,以下是一些关键指标的变化:

指标 旧系统(Flask) 新系统(FastAPI)
平均响应时间 ~1200ms ~250ms
QPS ~120 ~450
TP99延迟 >2s <400ms
文档更新周期 ≥3天 实时更新
开发效率 较低 明显提升

除了性能上的显著提升,团队的协作也更加顺畅。由于文档的自动化程度提高,产品、前后端沟通的会议频率明显下降。

此外,新框架让系统具备了更好的可扩展性。后期我们又引入了OAuth2认证、RateLimit、Prometheus监控等模块,整个系统逐渐向微服务化演进。


经验分享:新手起步的几点建议

如果你刚接触FastAPI,或者正在准备入门Python后端开发,下面是我亲身经历后总结的一些经验,希望能帮你少走些弯路。

✅ 从真实场景出发,构建你的第一个项目

不要一开始就啃教程。试着先找一个小需求,比如做一个自己的读书笔记系统、天气查询接口,或者像我一样做个用户管理模块。边做边学是最有效的。

✅ 熟练掌握ASGI服务器的部署方式

FastAPI依赖Starlette,所以推荐使用Uvicorn或Hypercorn作为运行引擎。部署到生产环境时,请务必使用Gunicorn搭配Uvicorn Worker。

gunicorn -w 4 -k uvicorn.workers.UvicornWorker app.main:app

同时记得开启HTTPS,可以用Nginx反代,安全又省事。

✅ 学会在合适的场景使用异步

不是所有的接口都适合异步。例如复杂的计算任务,反而更适合放进线程池处理;但对于I/O密集型任务(如数据库查询、HTTP调用),异步确实是杀手锏。

✅ 多用中间件解决问题

FastAPI提供了强大的中间件支持。比如我们可以用中间件统一拦截错误日志、添加请求耗时统计、限流控制等等。

@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    return response

数据流转过程-1


结语:后端之路,从选对工具开始

FastAPI不仅是一个优秀的Python后端框架,更是一个让你重新认识Python生态强大之处的入口。

在这个项目之后,我开始越来越多地参与一些中大型后端服务的开发。无论是在API设计、异步编程还是运维实践中,FastAPI都给我带来了极大的帮助。

如果你也在寻找一个高效、现代化、文档完备的后端框架,FastAPI绝对值得一试。希望这篇文章能让你少走弯路,顺利迈出Python后端开发的第一步。

祝你编码愉快!如果有什么疑问,欢迎留言讨论 😊

评论 0

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