FastAPI 教程

Chapter 11 · 企业级架构:像专家一样组织代码

📚 学完本章,你将能够:

  • 理解 Clean Architecture 的分层思想:为什么代码要分文件夹
  • 组织一个可维护的中大型 FastAPI 项目结构
  • 实现健康检查端点,让云平台和负载均衡知道服务状态
  • 暴露 Prometheus 指标,实现可观测性
  • 管理多环境配置(开发/测试/生产)

💡 场景引入

你的图书 API 从 5 个接口增长到了 50 个,涉及用户、订单、支付、通知多个模块。所有代码挤在一个 main.py 里,每次改代码都怕牵一发而动全身。新同事入职后花了三天才理清代码关系。

项目规模扩大后,代码的组织方式比代码本身更重要。本章教你像专业团队一样组织项目。

11.1 Clean Architecture:洋葱一样的分层

核心思想:内层(业务规则)不依赖外层(框架、数据库、UI)。外层可以替换,内层保持稳定。

分层架构
API 层(路由、Schema)
Service 层(业务逻辑、事务)
Repository 层(数据访问)
Model 层(数据库模型)

各层职责:

11.2 项目目录结构

项目结构
bookstore/
├── app/
│   ├── __init__.py
│   ├── main.py              # FastAPI 实例、lifespan、全局异常
│   ├── core/                # 配置、日志、安全工具
│   │   ├── config.py
│   │   ├── security.py
│   │   └── exceptions.py
│   ├── api/                 # 路由和请求/响应模型
│   │   ├── deps.py          # 全局依赖
│   │   └── v1/
│   │       ├── router.py
│   │       ├── endpoints/
│   │       │   ├── auth.py
│   │       │   ├── books.py
│   │       │   └── orders.py
│   │       └── schemas/
│   │           ├── book.py
│   │           └── user.py
│   ├── services/            # 业务逻辑
│   │   ├── book_service.py
│   │   └── order_service.py
│   ├── repositories/        # 数据访问
│   │   ├── base.py
│   │   └── book_repo.py
│   ├── models/              # 数据库模型
│   │   ├── base.py
│   │   └── book.py
│   └── db/
│       └── session.py
├── tests/
├── alembic/                 # 数据库迁移
├── Dockerfile
├── docker-compose.yml
└── pyproject.toml

11.3 多环境配置

开发、测试、生产环境的数据库地址、密钥、调试开关都不同。用 pydantic-settings 管理:

core/config.py
from pydantic_settings import BaseSettings, SettingsConfigDict

class Settings(BaseSettings):
    model_config = SettingsConfigDict(env_file=".env")

    ENV: str = "development"
    DEBUG: bool = False
    DATABASE_URL: str
    SECRET_KEY: str
    REDIS_URL: str = "redis://localhost:6379"

    @property
    def is_production(self) -> bool:
        return self.ENV == "production"

settings = Settings()

生产环境通过环境变量注入配置,不在代码中写死:

.env 文件(不提交 Git)
ENV=production
DATABASE_URL=postgresql+asyncpg://user:pass@db:5432/mydb
SECRET_KEY=super-secret-key-from-env

11.4 健康检查

Kubernetes 和云平台通过健康检查决定是否给你流量。你需要提供三种探针:

健康检查
from fastapi import APIRouter
from sqlalchemy import text

health = APIRouter(prefix="/health")

@health.get("/live")
async def liveness():
    return {"status": "alive"}  # 进程还活着

@health.get("/ready")
async def readiness(db: AsyncSession = Depends(get_db)):
    await db.execute(text("SELECT 1"))  # 数据库能连上吗?
    return {"status": "ready"}

11.5 Prometheus 监控

暴露指标让 Prometheus 抓取,Grafana 展示:

指标收集
from prometheus_client import Counter, Histogram, generate_latest

REQUEST_COUNT = Counter("http_requests_total", "Total requests", ["method", "endpoint", "status"])
REQUEST_DURATION = Histogram("http_request_duration_seconds", "Request duration", ["endpoint"])

@app.middleware("http")
async def metrics_middleware(request, call_next):
    start = time.time()
    response = await call_next(request)
    duration = time.time() - start
    REQUEST_COUNT.labels(request.method, request.url.path, response.status_code).inc()
    REQUEST_DURATION.labels(request.url.path).observe(duration)
    return response

@app.get("/metrics")
async def metrics():
    return Response(generate_latest(), media_type="text/plain")

🎓 课程总结

从第一章的 Hello World 到现在的企业级架构,你已经完成了后端工程师的完整成长路径:

1

基础篇

理解了 HTTP 请求-响应模型,能用 FastAPI 写 CRUD 接口,用 Pydantic 做数据校验,用依赖注入消除重复代码。

2

进阶篇

接入了真实数据库,实现了 JWT 认证和 RBAC 权限,处理了全局错误和日志,用异步提升了并发能力,用 WebSocket 实现了实时推送。

3

部署篇

用 pytest 保障代码质量,用缓存和限流提升性能,用 Docker 和 Nginx 部署到生产环境,用 Clean Architecture 组织大型项目。

下一步

打开 IDE,从零开始搭建一个项目。不要复制粘贴,手写每一行。遇到报错先读官方文档,再搜索。真正的掌握来自调试和解决问题的过程。祝你好运!

🎯 最终检测

问题 1
Clean Architecture 中,Service 层的主要职责是什么?
接收 HTTP 请求和返回 JSON
编排业务逻辑和管理事务边界
定义数据库表结构
处理 CSS 样式
解析:Service 层是业务逻辑的核心。它协调多个 Repository 完成复杂操作(如"下单"需要查库存、扣库存、创建订单),并管理事务边界(commit/rollback)。API 层只负责 HTTP 语义。
问题 2
为什么健康检查的 /ready 要查数据库,而 /live 不用?
因为 /live 比较懒
/live 只证明进程存活,/ready 证明服务能处理请求(依赖都正常)
因为数据库查询太慢
因为 /ready 是收费的
解析:Kubernetes 用 liveness 判断容器是否该重启,readiness 判断是否该给它流量。如果数据库连不上,进程还活着(live),但不应该接收请求(not ready)。
问题 3
生产环境的 SECRET_KEY 应该放在哪里?
直接写在代码里,方便管理
通过环境变量注入,不提交到代码仓库
写在 README 里
发给所有同事备份
解析:密钥、密码等敏感信息绝不能硬编码。环境变量、Docker Secrets 或 K8s Secret 是标准方案。.env 文件加入 .gitignore,代码仓库只留 .env.example 作为模板。