本页目录

全栈 II · 后端工程

对标:Berkeley CS169 / FastAPI 文档 / DDIA(数据视角)| 前置:web-01、db 线、os-02(并发)、net-02(HTTP) 深入 web-01 那条链里的应用服务器层——后端。以你的 FastAPI(Medusa)为标本,讲清后端的核心构件:路由与请求处理、ORM 与数据库交互(及其经典陷阱)、异步/并发模型(为什么现代后端爱 async)、认证授权、错误处理与日志。这是把"能跑的后端"写成"可靠的后端"的工程知识。

1. 后端的骨架:路由 → 处理 → 响应

后端骨架:路由→中间件→校验→处理→数据库→响应。

图 web-02.3后端骨架:路由→中间件→校验→处理→数据库→响应。

后端服务器的核心循环:接收 HTTP 请求 → 路由到对应处理函数 → 执行业务逻辑(常含数据库)→ 返回响应。FastAPI 里:

2. ORM 与数据库交互:方便背后的陷阱

N+1 查询:列表 1 次 + 循环每项 1 次 = N+1,改 JOIN 预加载 1 次。

图 web-02.2N+1 查询:列表 1 次 + 循环每项 1 次 = N+1,改 JOIN 预加载 1 次。

后端大量工作是与数据库对话。ORM(对象关系映射,如 SQLAlchemy)把数据库行映射成对象、让你用代码而非 SQL 操作——方便,但有必须懂的陷阱

方法论ORM 是便利层,不是 SQL 的替代品——你必须能看穿它生成的 SQL(db-02 的 EXPLAIN),否则性能问题无从查起。"懂 ORM 底下的 SQL"是后端工程师和调包侠的分水岭

3. 异步与并发:现代后端为什么爱 async

异步事件循环:单线程遇 I/O 挂起去干别的(I/O 密集高效 vs 阻塞线程池)。

图 web-02.1异步事件循环:单线程遇 I/O 挂起去干别的(I/O 密集高效 vs 阻塞线程池)。

后端大量时间在等待——等数据库、等外部 API(Medusa 等 DeepSeek)、等磁盘。这是 I/O 密集(不是 CPU 密集)。两种应对模型(🔗 os-01 进程/线程、par 线):

关键认知async 擅长 I/O 密集(大量等待),不加速 CPU 密集(CPU 满载时事件循环也堵)。Medusa 后端查数据库、调 LLM API 都是 I/O 密集——async 是对的选择;但若有重计算(如本地跑 embedding)要丢给线程池/进程池,别堵住事件循环。"async 处理等待、多进程处理计算"是后端并发的分工原则

4. 认证、授权与会话

5. 错误处理、日志与可观测性

生产后端的成熟度体现在出错时的表现

6. 练习与要点

例 1(抓 N+1) 写一段"取文章列表再循环取每篇的标签"的 ORM 代码,开 SQL 日志数查询次数,然后改成 JOIN 预加载——亲眼看 N+1 从几百次查询降到 1 次。后端最高频的性能修复。

例 2(async 判断) 判断三个后端任务(查数据库、调 LLM API、本地跑 embedding)哪些适合 async、哪个要丢进程池——把"async 治 I/O、进程治 CPU"用到 Medusa

例 3(错误分层) 给"用户请求不存在的文章"和"数据库连接断了"设计不同的错误响应(404 vs 503,用户看到什么、日志记什么)——练"预期错误 vs 意外错误"的分层处理\(\blacksquare\)

▶ 关联实验 L12(极简 HTTP 服务器)labs/L12-http-server/ 已在 net-02 引入——从 socket 到 HTTP,是本页 FastAPI 底下那一层。理解了它,框架就不是黑盒。


下一页:全栈 III——浏览器与前端工程:那条链的另一端,React 怎么把数据变成界面、浏览器怎么渲染、前端性能与工程化(你的 Vite 构建正在此列)。