生态纵览:数据库、五个框架、REST/GraphQL、前端选项¶
这是第 2 章拆解的最后一篇,也是选型论证的「上货」环节。 前面立了尺子 (02 的视角、03 的打分表),这一篇把候选全部摆上桌:数据库怎么分类、 Rust 生态里有哪些驱动和 ORM、五个 Web 框架用同一段代码同台比、 API 该走 REST 还是 GraphQL、前端除了 JavaScript 还有哪条路。 主线例子:同一个「反向 Hello World」小 API,在五个框架里各写一遍—— 谁啰嗦、谁薄,一比便知。
1. 顶层全景¶
数据层:数据库三视角(CAP / ACID-BASE / 数据表示)→ 产品地图 → Rust 驱动与 ORM 清单
应用层:五个框架同题作文(Rocket / Actix / Axum / Warp / Tide)
API 形态:REST(约束)→ Swagger/OpenAPI(描述)→ GraphQL(查询语言)
表现层:JS/TS 打包管线(Webpack/Vite)→ CSS 框架 → WebAssembly(Rust 前端)
图说:从离数据最近的一层走到离用户最近的一层,每层都先讲「有哪些类」再讲「Rust 里有哪些」。
2. 重新看技术栈:它是分层的¶
书里的技术栈图景(这一句话把全章结构定了):
技术栈大概率是分好几层的:持久层选数据库;数据库上面要一层接口/适配层 (不直连数据库,避免被某一家锁死——lock-in);再往上是 Web 框架 (HTTP、DOM 这些标准你也不该直接用,该用打包好的库);再往上是对外 API; 最上是 UI 层1。
「避免锁死」是这条链的原则: 书里明说,直连某一种数据库技术会把应用锁进去, 「通常应该尽可能避免 lock-in,好让可能性保持开放」2。这就是 ORM/适配层存在的架构理由。
3. 数据库:三个分类视角¶
先交代方法:数据库技术可以从好几个视角分类。 视角不同,问的问题不同, 得到的候选族也不同3。
3.1 分布式视角:CAP 定理¶
CAP 定理:一个分布式数据存储,三个保证里最多同时给两个4:
| 保证 | 含义 |
|---|---|
| C 一致性(Consistency) | 谁读数据,都拿到最近一次写入的值 |
| A 可用性(Availability) | 每个请求都收到非错误的响应(哪怕不是最新数据) |
| P 分区容错(Partition tolerance) | 通信失败、消息丢失时,系统照常运转 |
三个里取两个,理论上有三种组合;但 P 是必选项(网络一定会断), 所以现实中只有两族:
- CP 数据库: 实例之间一旦不一致,就把出问题的实例关掉拒收请求, 等分区恢复、一致性修好了再开门;
- AP 数据库: 优先可用性——实例一直跑,偶尔端出旧版本的数据,直到一致性恢复5。
要选的其实是这道价值题: 你想「数据永远一致,哪怕偶尔访问不到」, 还是「永远能访问,哪怕偶尔拿到过期的」6。
3.2 事务视角:ACID 对 BASE¶
ACID(传统关系库的事务保证)7:
| 字母 | 含义 |
|---|---|
| A 原子性 | 事务要么整个成功、要么整个不算,没有中间态 |
| C 一致性 | 数据库里不允许存在自相矛盾的状态 |
| I 隔离性 | 并发执行的事务,效果等同于挨个顺序执行,互不干扰 |
| D 持久性 | 一旦提交,之后系统宕机也能找回来 |
BASE(分布式系统里「基本可用」一系的口号,与 AP 配套)8:
| 词 | 含义 |
|---|---|
| Basically available(基本可用) | 数据不一致时,读写照样进行,之后再对账 |
| Soft state(软状态) | 任何时刻你都不能确定数据已对账完没有 |
| Eventually consistent(最终一致) | 放着不写,系统自己会收敛到一致,之后每次读都一样 |
怎么选: 要「立刻的正确」选 ACID;要「永远能服务、正确晚点到」选 BASE。
3.3 数据表示视角:关系 vs NoSQL¶
关系库(RDBMS): 数据组织成互相关联的表,用键(key)引用其他表。关系的度数:
- 一对一: 一条记录对应另一条;
- 一对多/多对一: 一条对应多条;
- 多对多: 两边都是多条——没法直连,要拆成两条一对多(中间那张表叫 mapping,映射表)。 书里给的例子正是工单系统的订阅:一个项目经理能订阅多个事件,一个事件有多个订阅者, 中间必须有一张映射表9。
NoSQL(「非关系」的大筐,常见三族)10:
| 族 | 组织方式 |
|---|---|
| 键值存储(key-value) | 按键取数;键可以灵活,但除此之外没有任何组织原则 |
| 文档库(document) | 数据组织成文档,可带层级和嵌套文档;最好不跨类型关联 |
| 图库(graph) | 节点连节点成图;查询就是沿图 traversal(遍历) |
书里的小贴士:数据不规整时,关系库的严格表结构是负担,NoSQL 对 schema 灵活, 非规整数据好塞11——「格式动态」那个伏笔(第 11 章)在这里已经埋了一次。
3.4 产品地图与本书的选择¶
| 产品 | 定位 |
|---|---|
| PostgreSQL | 开源关系库,主打可扩展和 SQL 标准兼容 |
| MariaDB/MySQL | 最常见的开源关系库(被 Oracle 收购后有社区分支 MariaDB) |
| MongoDB | 文档 NoSQL,schema 直接写 JSON,查询用 JavaScript |
| Redis | 键值库,常当缓存和消息中介用(第 10 章还会回来) |
| SQLite | 嵌入式关系库,零配置;全世界用量最大的数据库引擎 |
本书的选择与理由: 从 SQLite 起步——零配置、教学友好; 而且故意用它引出 ORM:万一以后要换库,有了 ORM 就不用重写应用12。 这个「万一」不是假想:第 4 章就真的从 SQLite 迁去 MariaDB 了(那一章会领教这次迁移有多烦)。
4. Rust 的数据库生态:选 crate 的六条军规¶
解决什么问题: 生态里候选一堆,怎么挑库。书里给了一张评估清单, 这张清单不只适用于数据库,选任何 crate 都能用13:
| 军规 | 看什么 | 为什么 |
|---|---|---|
| 合目的 | 只选真用得上的;设计期不充裕就按最小来 | 避免过度设计 |
| 接受度 | 多少项目在用、下载量、GitHub stars | 需求越大,软件越成熟 |
| 团队规模 | bus factor(巴士因子):关键知识集中在几个人身上? | 一人项目=随时可能消失 |
| 最近提交 | 上次更新什么时候 | abandoned(被弃)的库=没有支持 |
| 许可证 | 法律上能不能用 | 别等写完才发现不能用 |
| 版本号 | 语义化版本:major(破坏性)/minor(新特性)/patch(修 bug) | 最不牢靠的指标,但 breaking change 风险分级有用 |
生态里的具体候选(原书清单): MySQL / mysql_async(同步与异步两版)、 Postgres / tokio-postgres、Redis / darkredis、Rusqlite、Mongodb(官方驱动)、 SQLx(编译期检查 SQL 查询的工具包,无 DSL 附加层,支持 PostgreSQL/MySQL/SQLite)、 Diesel(成熟的 ORM 和查询构造器)、SeaORM(支持异步的 ORM); 迁移工具:diesel_migrations、refinery、migrant14。
两个原则的提醒(书里原话口径): 不是手上有什么就全上; 用你需要的那么多,但别更多——这就是 KISS(Keep It Simple, Stupid) 和 YAGNI(You Ain't Gonna Need It)两条设计原则15。
5. 五个框架同题作文¶
解决什么问题: Rust 的「框架版图」到底什么样。书里的判断先放在这:
这是 Rust 生态仍然「falls short(差一截)」的领域。Ruby/Java 有成熟的全家桶 (Rails、Spring),Rust 还没老到能长出那样的东西——也许得先看着类似的框架 在 Rust 里兴衰一轮,才会出现一个像 Rails 那样完整顺手的16。
还有一个数字佐证:Web 编程类 crate 里自称 simple(简单)的占 20%, 而全体 crate 里只占 12%——「自称简单,经验上却往往 simple 在缺功能」17。
评测方法:同题作文。 每个框架实现同一个「反向 Hello World」微 API:
客户端 POST /greeting,带 JSON:{"message":"hello"}
│
▼
服务端:把 message 记进日志,回一个 JSON:{"acknowledged":"hello"}
│ (HTTP 状态 202 Accepted——「收到了,不保证处理结果」)
▼
顺便:GET / 返回一行用法说明(curl 命令)
图说:一个真收输入、真产输出的微 API——「像 REST API 那样工作,而不是返回静态文本」。
为什么是它而不是静态 Hello World: 书里点明——这个例子已经包含任何 Web 应用 都逃不掉的三件事:数据定义(Greeting/Acknowledgement 两个结构体)、 请求处理函数、引导(bootstrap,把应用配好启动起来持续监听)18。 任何 Web 应用都有这三个逻辑单元,不管叫什么名字。
5.1 Rocket:宏最多,魔法最重¶
Rocket 曾被视为 Rust 的「凤凰框架」——很多人当它死了,又涅槃; 书里写作时已经发了 55 个版本,正在成熟到 0.5(带一堆破坏性变更)。 能力清单:路由、数据解析(请求体→Rust 结构体)、请求守卫(request guards, 函数参数形式的横切检查——比如统一查 API key)、Responder(从类型造响应的抽象)、 状态管理、六种数据库驱动支持、Fairings(Rocket 版的中间件:全局应用、 不能短路流水线、能阻止应用启动)19。
代码特征:#[get("/")]、#[post("/greeting", format = "json", data = "<greeting>")]
这样的属性宏满天飞;#[launch] 替你造出 main 函数(文件里你看不到 main,
但 Rust 程序不可能没有 main——宏帮你生成了)20。
宏的代价(书里的硬数字): 31 行源码,宏展开后 479 行21。
Rocket 帮你干了大量活,也替你藏了大量东西。此外书里还点了一处冗余:
routes![index, greeting] 收集的路由,其实前面属性宏里已经写过了22。
5.2 Actix Web:演员模型出身,宏少了一半¶
Actix 家族实现的是 actor 模型(把并发单元封装成互相发消息的 actor);
actix-web 是其 Web 支持。同题作文代码结构相同:同样的结构体、类似的 handler,
#[actix_web::main] 启动,HttpServer::new(...).bind(("127.0.0.1", 8000))23。
数字:宏展开 272 行(比 Rocket 的 479 少了一大截)24。
5.3 Axum:Tokio 家亲儿子,「不为没用的东西付钱」¶
解决什么问题: Tokio 生态(文件系统、定时器、调度、HTTP 库 Hyper、gRPC、 低层网络、tracing)需要一个用着顺手、模块化的 Web 框架——Axum 就是这个团队 自己做的副项目25。
同题作文:路由用 Router::new().route("/", get(index)).route("/greeting", post(greeting)),
handler 参数直接用提取器 Json(greeting): Json<Greeting>——比宏直白得多。
宏展开只有 258 行,书里的评价:「We do not have to pay for what we do not use
(不为不用的东西付钱)」26。
选择落锤: 这本书后面全程用 Axum。理由在这一节已经摊开了: 魔法少(宏展开短)、站在 Tokio 生态正中间、模块化(缺什么用别的 crate 补)。
5.4 Warp:函数式风味,美与险并存¶
Warp 不自称 Web 应用框架,它是 Tokio 及其 HTTP 实现 Hyper 上面的一层抽象。
没有任何宏,一切都是函数——get().and(path::end()).map(index)、
warp::serve(index_route.or(greeting_route))。书里忍不住夸:
这些语句「上升到诗意的高度」27。
但同一个特性也是坑:
- 链式语句一长,类型推断会复杂到 rust-analyzer(那个语言服务器)当场 panic, VS Code 只能显示省略号;
- 少写一个括号,IDE 会刷出一大片与真因无关的报错;你若不去修真正的括号, 而是顺着那些报错瞎补,代码就毁了28。
结论:值得持续关注,但写业务前要想清楚链式 filter 的维护成本。
5.5 Tide:最谨慎的 API,最快的极限¶
Tide 自称 minimal and pragmatic(极简、务实),建在 async-std(异步版标准库)上。
同题作文里它的 handler 返回 Result(可能带错误)而不是裸响应——
书里称这是「a careful, considerate approach(谨慎周到的做法)」;
响应的构造也全显式:状态码、正文、content-type 一行行来。
Tide 还是唯一在示例里附了测试 curl 命令的框架——「这本该是标配」29。
书里对 Tide 的总结带着惋惜:Rust 的快速开发框架,「rapid」的地方在于 你很快会碰到它们的极限30。
5.6 同题作文的对照表¶
| 框架 | 语法风味 | 宏展开后行数(原书实测) | 书里的一句话定性 |
|---|---|---|---|
| Rocket | 属性宏密集 | 479 | 功能全但魔法重,曾「死而复生」 |
| Actix Web | 轻宏 + builder | 272 | actor 模型家族,中庸 |
| Axum | 几乎无宏,提取器 | 258 | 「不为不用的付钱」→ 本书选择 |
| Warp | 纯函数链式 | —(类型复杂到 IDE 吃不消) | 诗意但险 |
| Tide | 保守显式 | — | 谨慎,但上限来得快 |
顺带记住两个贯穿全书的库: Serde(序列化 = 把内存结构转成可传输文本、反序列化 = 反过来,这对动作的事实标准—— 把 Rust 结构体转成 JSON 文本叫序列化,反过来叫反序列化;五个框架全都在用它)31; DTO(data transfer object,数据传输对象)——Greeting/Acknowledgement 就是两个 DTO:只为传输定义、不含业务逻辑的结构体32。第 4 章前后端共享代码时, DTO 还是主角。
6. API 形态:REST、Swagger、GraphQL¶
6.1 REST:一组约束,不是标准¶
先纠正一个普遍误解:REST 不是标准。 没有「合规/不合规」的判定, 它的约束(constraint)只是把 API 叫成 RESTful 的资格线;没全做到也不妨碍 它是个能用的 API33。
REST 的核心思想:直接拿应用层协议(HTTP)当消息机制—— 用 HTTP 方法当 CRUD 的标记(POST 建、GET 读、PUT/PATCH 改、DELETE 删), 不为同样的概念再造一层新协议34。四条主约束:
| 约束 | 含义 |
|---|---|
| Client-server separation | API 提供方与消费方分开设计 |
| Uniform interface | 所有资源共用一个格式,消费方好写 |
| Statelessness(无状态) | 服务器不在请求之间存信息;每个请求自带全部所需信息 |
| Layered system | 可以插中间层(缓存、负载均衡)而不破坏链条 |
「无状态」是后面很多章的隐形前提: 第 7 章的会话、第 10 章的缓存, 全在「服务器原则上不记上次的事」这个约束下做文章。
6.2 Swagger/OpenAPI:给 API 一张说明书¶
REST 刚流行时大家各写各的,很快有人觉得该有个描述格式(注意:是「描述一个具体服务」, 不是「规定怎么写」)。Swagger Specification 登场:能描述端点与操作、 输入输出参数、认证方式、schema、许可证等信息;后来长成了 「编辑规格文件 → 生成 API」的整个工具生态35。
一个史实(书里有,值得记):2015 年 Swagger 规格捐给了 Linux 基金会, 此后改名 OpenAPI Specification——所以你在别处撞见 OpenAPI,就是它的正式名, Swagger 这个名字留在工具链上(Swagger Tools)36。本书用 Swagger 给工单 API 出文档(后面章节)。
6.3 GraphQL:让客户端点菜¶
GraphQL 是 Facebook 出品、2015 年开源的 API 查询语言: 客户端自己定义响应的格式,服务器只发被点的东西37。它多解决的问题:
- 资源打包: 一个请求拿多种资源,不用连环请求;
- 类型定义: 资源关系被类型化,不合法的查询在服务器端直接被拒,省掉昂贵的解析逻辑;
- 免版本化: API 随客户端需求演化,不用 v1/v2 并存。
书里对 GraphQL 的态度是清醒的克制: 这些好处是真的,但「一开始就全都需要」 很少见——API 小、消费方近(比如自家前端)时,一个个资源地 REST 伺候就够; 等灵活性的收益真的超过成本再上,这才叫增量开发38。
7. 前端选项:三条路¶
前提(书里明确): 前端技术完全不用换——任何前端最后都产出 「普通旧 HTML/CSS/JS 文件」,对后端框架来说那不过是些静态文件,照常托管就行39。 所以 Angular、React、Vue、Svelte、Elm,全都可选。这本书自己选了第三条路 (WebAssembly),但先把三条路都摆全。
7.1 JS/TS 管线¶
Node.js 之后 JS 生态爆炸,于是有人在上面加了一层类型——TypeScript: 「编译期强制类型」——之所以加引号,是因为 TS 会被转译(transpile)回普通 JS, 产物仍是人能读的源代码,浏览器照旧跑它的 JS 引擎40。
前端源码要经过打包(bundling,产出可分发的静态文件) 才能给浏览器吃, 两大打包器:
| 工具 | 干什么 |
|---|---|
| Webpack | 收集代码和资源 → 转译 → 压缩 → 混淆 → 打成最终包;还能边开发边增量打包(支撑热更新) |
| Vite | 目标相同,主打性能优化;越来越多项目的默认选择 |
(书里那个调侃网站的截图也值得会心一笑:一个专门显示「距上一个 JS 框架发布过去了几 天」的网站——前端框架的潮流,眨眼就换41。)
7.2 CSS 框架¶
样式这层的进化链:内联样式 → CSS(样式抽到单独文件、用 class 归组)→ LESS/Sass(CSS 的超集,加变量和动态构造,用前得先转译回 CSS)→ 真正的 CSS 框架 (自带精心设计的布局类和 UI 组件类):Bootstrap、Foundation、UIKit、Tailwind CSS42。
7.3 WebAssembly:Rust 前端的地基¶
先解释词。 WebAssembly(Wasm)= 在浏览器的隔离沙箱里跑编译好的二进制程序。 比 JS 快,因为它不是解释执行的;但它不打算取代 JavaScript—— 它拿不到浏览器 API(比如操作页面的 DOM),要用它得靠一层 JS 在中间传话43。
对 Rust 的意义: 目标不是「Wasm 快不快」,而是「能不能拿 Rust 替代 JS 写前端」。 答案是:可以,但离不开 JS——工具链会替你生成那些「JS 灰浆」, 你在意识不到它的情况下写 Rust44。
落地路径: Rust 编译成 Wasm 文件 → 嵌进普通 HTML/JS 里。 没有第二条路;「即使不碰那段 JS,它也在」——管线里多一步,得认45。
三个 Rust-Wasm 框架(写书时的候选):
| 框架 | 风格 |
|---|---|
| Dioxus | 类 React 的写法,「跑得到处都是」 |
| Yew | 真正的 Web 应用框架(组件、HTML 模板、服务端渲染)——本书的选择,第 3、4 章展开 |
| Sycamore | 响应式风格,语法更简、打字更少 |
两个澄清(书里特意写的注释): Wasm 不属于 Rust——写书时支持 14 种语言, 任何能出二进制的编译器都行;Wasm 也救不了你不用 HTML/CSS—— 它只是让前端应用「由一颗 Rust 的心驱动」46。
8. 作者的判断与证据(分开标)¶
有出处的: CAP 定理与 ACID/BASE 的表述是学界通行;Swagger→OpenAPI 更名有 Linux 基金会捐赠的公开史实36;宏展开行数(479/272/258)是原书实测212426。
作者自己的评估:
- 「Rust 框架生态差一截、全家桶要等一轮兴衰」是作者判断,当时成立,今天仍在演化;
- 对 Warp 的诗意与风险、Tide 的惋惜,是作者的口味;
- 「同题作文」这个评测法是作者设计,不是行业基准(公平性依赖题目本身)。
9. 边界与局限¶
- 版本快照: 五个框架的版本号、宏展开行数、甚至存亡(Rocket/Tide 后来各有沉浮) 都是写书时的快照——选框架前务必按第 4 节那六条军规重查现状。
- 前端部分只导览: JS 框架本身怎么写不在本书范围(第 1 章就声明了)。
- CAP/ACID 是深水区的入口: 副本一致性协议、分布式事务本书未展开, 够选型判断,不够工程实施。
10. 可带走的¶
- 技术栈是分层的: 持久层 → 适配层(防锁死)→ 框架层 → API 层 → UI 层; 「避免 lock-in」是适配层存在的理由。
- 数据库三视角: CAP(分布式下一致/可用/分区容错三选二)、ACID vs BASE (立即正确 vs 永远可服务)、关系 vs NoSQL(规整数据 vs 灵活 schema)。
- 选 crate 六军规: 合目的、接受度、bus factor、最近提交、许可证、语义化版本。
- 任何 Web 应用三件套: 数据定义、请求处理、bootstrap;选框架就是在选 这三件套的「写法税」——同题作文一比便知(Rocket 479 行 vs Axum 258 行的宏展开)。
- REST 是约束不是标准; 「无状态」是后面会话与缓存章节的地基。
- Swagger 已改名 OpenAPI(2015 年捐给 Linux 基金会),别在文档里用旧名当正式名。
- GraphQL 的香要配「真需要」吃: 资源打包、类型化、免版本,API 大了才值回票价。
- Rust 前端的真相: Wasm 跑在沙箱里、够不着 DOM、离不了 JS; 工具链替你藏住 JS,但管线里永远有它一步。
11. 原文地图¶
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 技术栈分层与防锁死 | Selection of a Tech Stack | text/12-fm-the-architecture-frenzy.txt:846(搜「distinct layers」)、:849(搜「lock-ins」) |
| CAP 定理三保证 | 同上 | text/12-fm-the-architecture-frenzy.txt:870(搜「CAP theorem」)、:875(搜「most recent write」) |
| CP / AP 两族 | 同上 | text/12-fm-the-architecture-frenzy.txt:895(搜「CP database」)、:898(搜「AP database」) |
| ACID 四项 | 同上 | text/12-fm-the-architecture-frenzy.txt:908(搜「ACID」)、:912(搜「Atomicity」) |
| BASE 三项 | 同上 | text/12-fm-the-architecture-frenzy.txt:925(搜「BASE」) |
| 关系度数与多对多映射 | 同上 | text/12-fm-the-architecture-frenzy.txt:948(搜「One-to-one」)、:952(搜「Many-to-many」) |
| NoSQL 三族 | 同上 | text/12-fm-the-architecture-frenzy.txt:959(搜「Key-value」)、:962(搜「Document database」)、:965(搜「Graph database」) |
| SQLite「全世界用量最大」 | 同上 | text/12-fm-the-architecture-frenzy.txt:1007(搜「most used database」) |
| 选 crate 六方面 | 同上 | text/12-fm-the-architecture-frenzy.txt:1024(搜「Fitness for the purpose」)、:1032(搜「bus factor」)、:1038(搜「license」) |
| 驱动/ORM 清单 | 同上 | text/12-fm-the-architecture-frenzy.txt:1078(搜「SQLx」)、:1081(搜「Diesel」)、:1084(搜「SeaORM」) |
| KISS / YAGNI | 同上 | text/12-fm-the-architecture-frenzy.txt:1097(搜「KISS」) |
| 框架生态差一截 | 同上 | text/12-fm-the-architecture-frenzy.txt:1103(搜「falls short」) |
| 20% 自称 simple | 同上 | text/12-fm-the-architecture-frenzy.txt:1106(搜「20%」) |
| Rocket 能力与 Fairings | 同上 | text/12-fm-the-architecture-frenzy.txt:1115(搜「55 versions」)、:1137(搜「Fairings」) |
| 三逻辑单元(数据/处理/bootstrap) | 同上 | text/12-fm-the-architecture-frenzy.txt:1326(搜「Data definition」)、:1332(搜「Bootstrap」) |
| Serde 与 DTO | 同上 | text/12-fm-the-architecture-frenzy.txt:1287(搜「serialize」)、:1292(搜「Serde」) |
| Actix 代码与 272 行 | 同上 | text/12-fm-the-architecture-frenzy.txt:1354(搜「actor model」)、:1477(搜「272」) |
| Axum 定位与 258 行 | 同上 | text/12-fm-the-architecture-frenzy.txt:1483(搜「side-project」)、:1642(搜「258 lines」) |
| Warp 诗意与 IDE 之险 | 同上 | text/12-fm-the-architecture-frenzy.txt:1663(搜「Filter」)、:1792(搜「word soup」)、:1805(搜「ellipses」) |
| Tide 显式构造与 curl 示例 | 同上 | text/12-fm-the-architecture-frenzy.txt:1952(搜「explicit」) |
| REST 四约束 | 同上 | text/12-fm-the-architecture-frenzy.txt:1970(搜「architecture style」)、:2000(搜「Statelessness」) |
| Swagger → OpenAPI | 同上 | text/12-fm-the-architecture-frenzy.txt:2013(搜「Swagger Specification」)、:2043(搜「Linux Foundation」) |
| GraphQL 三好处 | 同上 | text/12-fm-the-architecture-frenzy.txt:2057(搜「query language」)、:2061(搜「Resource bundling」) |
| JS/TS 与打包双雄 | 同上 | text/12-fm-the-architecture-frenzy.txt:2090(搜「transpiled」)、:2100(搜「Webpack」)、:2105(搜「Vite」) |
| CSS 进化链 | 同上 | text/12-fm-the-architecture-frenzy.txt:2128(搜「LESS」)、:2131(搜「Tailwind」) |
| Wasm 真相(沙箱/DOM/JS) | 同上 | text/12-fm-the-architecture-frenzy.txt:2137(搜「sandbox」)、:2147(搜「14 different languages」) |
| 三 Rust-Wasm 框架 | 同上 | text/12-fm-the-architecture-frenzy.txt:2165(搜「Dioxus」)、:2170(搜「Yew」)、:2173(搜「Sycamore」) |
| 章节结论 | 同上(Conclusion) | text/13-fm-conclusion.txt:1(搜「Conclusion」) |
5.7 五个框架的完整对照展开(承重机制的更多细节)¶
这一节把第 5 节的同题作文再展开一层——每个框架的「完整能力清单」和它没写出来的 代价,都是原书正文里的原话口径。37
Rocket 的完整能力单(书里逐项列的):路由(把 handler 绑到路径与方法, 并从请求里提取信息做充分性/有效性检查);数据解析(把请求体加工成 trait 定义好的 Rust 数据格式);请求守卫(request guards)——加在 handler 函数参数上的 附加要求,条件不满足就阻止 handler 触发,「比如在任何使用它的 handler 执行前 统一检查 API key」;Responder(从支持的类型造响应的抽象);状态管理 (应用级一次初始化昂贵资源 / 请求级局部状态);数据库支持(官方列了六种驱动的 五种库:MongoDB、MySQL、MSSQL、PostgreSQL、Redis、SQLite);Fairings—— Rocket 式的中间件,三个 twist:全局应用、不能短路流水线、能阻止应用启动38。
书里紧接着的那句对比是本章最重的一锤:Laravel(PHP)开箱自带捆绑的 ORM、 查询构造器、依赖注入、反向路由、RESTful 控制器、模板、迁移与种子、分页、 表单验证、缓存、任务、认证、脚手架、全文搜索——「而 Rocket 覆盖了 Web 应用的基本必需之后,几乎没有更多」。Rust 生态缺的不是「能写 API」, 而是这条长长的清单;这本书第 7 到 10 章本质上就是在用手工+专门 crate 的方式把清单补回来39。
Actix Web 的出身:Actix 家族实现的是 actor 模型——并发单元被封成 互相发消息的 actor;actix-web 是它的 Web 支持,同为异步事件驱动。 同题作文里「同样的数据结构、类似的 handler、bootstrap 也在」, 宏展开 272 行(对照 Rocket 的 479)——「metaprogramming 少了一点、冗余 少了一点、生成的代码少了一大截」40。
Axum 的家世再补一层:Tokio 不是只有调度——它自己就是「成熟的富功能 非阻塞 I/O 平台」:文件系统、定时器、调度、HTTP 库(Hyper)、gRPC 客户端 与服务端、低层网络、tracing,全有。Axum 是这个团队做的人体工学 + 模块化的 Web 框架——「我们最感兴趣的那个」41。258 行的宏展开背后还有 一句生态判断:「已经有一堆 crate 在打算给 axum 加功能,后面只会更多」—— 微框架的正确用法不是等它长全,而是缺什么装什么。
Warp 的类型之殇(展开):书里给了一张截图的描写——VS Code 对一条 filter 链的推断类型长到只能显示省略号;链式语句少一个括号,IDE 报错 刷屏,而且那些报错与真正的病因无关;「如果不去修真正的括号,而是顺着 报错瞎补,代码就彻底毁了」。这段是「类型推断 + 长链式 API」交互陷阱的 标准教案42。
Tide 的保守与诚实:tide = "0.16.0" 配 async-std(把标准库 API
整套做成异步版的项目);handler 返回 Result(可能带错误)而不是裸响应,
响应用 builder 一行行显式拼(状态码、正文、content_type);
「Tide 是唯一给示例附了测试 curl 命令的框架——这本该是标配」。
而那句「Rust 的快速开发框架,rapid 在于你很快会碰到它们的极限」,
是作者对当时整个生态的定性43。
6.4 REST、Swagger、GraphQL 的更多细节¶
REST 那四条约束各补一刀(原书口吻):客户端-服务器分离是「把 API 提供方 与消费方作为设计上的分野」;统一接口是「所有资源一个通用格式,消费方好造」; 无状态是「服务器不指望在请求之间存信息——每个请求必须自带全部所需」; 分层系统让「缓存、负载均衡这类中间层可以插进来而不破坏链条」。 书里的定位句:「REST 不是标准,所以它没有合规不合规;满足约束的 API 配叫 RESTful,不满足的也照样可以是个能用的 API」44。
Swagger/OpenAPI 的史实链:行业先有的 REST、后有的混乱,于是有人要做 「描述一个具体服务的标准格式」(注意:不是「怎么写」的规范)。Swagger 规格 能描述端点与 CRUD 操作、输入输出参数、认证方法、schema、许可证等元信息; 后来长成了「编辑规格文件 → 生成 API」的整个生态。2015 年捐给 Linux 基金会 后改名 OpenAPI Specification,迭代了三个大版本;Swagger 这个名字留在 工具链上(Swagger Tools)——所以你在 2026 年的文档里看到 OpenAPI 是正式名、 Swagger 是工具名45。本书后面用它给工单 API 出交互文档。
GraphQL 的三项好处与那道克制的闸门(再展开):资源打包(一次请求拼装 多种资源,消灭连环请求);类型定义(资源关系被类型化,无意义的查询在服务端 直接被拒,省掉昂贵的解析逻辑);免版本化(API 随客户端需求演化,不必 v1/v2 并存)。但书里连说三次「不必一开始就需要」:API 小、消费方近(自家前端)时, 逐个资源地 REST 就够;等灵活性的收益真切超过成本再迁,才叫增量开发46。
7.4 前端三选项的更多细节¶
JS/TS 的翻译链(书里一层层剥的):Node.js 引爆生态 → 代码量爆炸 → 有人想加一层类型保险 → TypeScript 诞生。关键细节:TS 不是编译到机器码, 是转译(transpile)回普通 JS——产物仍是人可读的源代码,可以再压缩混淆, 但浏览器跑的还是 JS 引擎那套。前端源码到可部署静态文件之间的那道工序叫 打包(bundling / 产出 distribution);Webpack 一路收集、转译、压缩、 打成最终包,还支持边开发边增量打包(热更新的地基);Vite 同目标、主打性能, 「越来越多项目的默认选择」47。
CSS 层的进化链(一句话版):内联样式失控 → CSS 把样式抽到文件、用 class 归组 → 重复仍在(CSS 里还有重复)→ LESS/Sass 给 CSS 加变量与动态构造 (超集,用前得转译回 CSS)→ 真正的框架(Bootstrap、Foundation、UIKit、 Tailwind CSS)直接给成套的布局类和组件类,「界面漂不漂亮,用户第一眼就看它」48。
Wasm 前端三个框架的定位(书里就给了各一句):Dioxus——类 React 语法、 「一处写、到处跑」;Yew——Angular 那种完整的 Web 应用框架(组件、 HTML 模板、服务端渲染),本书的选择;Sycamore——响应式风格、语法更简。 选择建议书里没给,但口径很清楚:这个领域新得一切都在快速演化,锁定任一 都要接受跟它一起进化49。
3.5 数据库视角再展开:CAP 的场景感、ACID 的逐字义、产品地图的用途¶
CAP 的场景感(为什么 P 没得选)。 三保证里,分区容错看起来最「可放弃」, 书里一句话堵死:网络分区不是「会不会发生」的问题,是「什么时候发生」的问题—— 机器之间的通信一定会断,断了还要正常运转,就只有两种活法:CP(不一致就把自己 关掉,宁可不可用)或 AP(一直可用,偶尔端出旧数据)。「想追求 CA 的, 出于现实原因可以忽略」50。这个三选二的「二」不是任意二,是在 P 已经锁定 的前提下,选 C 还是选 A——把它记成「分布式数据库的第一道价值题」。
ACID 逐字再敲一遍(每个词对应一类真实事故):
- 原子性的反面是「做了一半」:转账扣款成功、入账失败——没有原子性, 数据库里就允许存在这种半成品状态;
- 一致性的反面是「自相矛盾」:外键指向不存在的行、库存为负—— 一致性保证任何时刻打开库都不会读到讲不通的状态;
- 隔离性的反面是「互相踩」:两个人同时买最后一件库存,都成功—— 隔离让并发事务的效果等同于排队执行;
- 持久性的反面是「白干了」:提交之后断电,数据必须还在51。
BASE 的读法: 它不是 ACID 的「对立阵营」那么非黑即白,而是 AP 系统 把「正确」从「此刻正确」放宽成「最终正确」:基本可用(不一致时读写照常)、 软状态(对账前谁都说不准)、最终一致(停止写入后系统自己收敛)。 「如果停止写库,它最终会恢复到一致,此后每次读都一样」——这句是 书里对 eventually consistent 的完整定义52。
产品地图的正确用法(一张表背下来,用途是「定位谈话」而不是「背名录」): PostgreSQL(开源、可扩展、SQL 标准)、MariaDB/MySQL(最常见的开源关系库, 注意 Oracle 收购史和社区分叉)、MongoDB(文档库,schema 写 JSON、查询用 JS)、 Redis(键值库,缓存与消息中介的常客——第 8、10 章它都会回来)、 SQLite(嵌入式、零配置、全世界用量最大的数据库引擎)。 书里的用法宣言值得再引一次:从 SQLite 起步是教学选择,故意用它引出 ORM—— 「万一以后要换库,有 ORM 就不用重写应用」;这个「万一」在第 4 章真实发生了53。
4.1 选 crate 六军规的逐条展开¶
为什么「合目的」排第一: 其余五条都是「这个库好不好」,这条问的是 「这个库好不好跟你有没有关系」。已知只用一种数据库时,看别的驱动 就是浪费;设计期不充裕就按最小集来——「避免过度设计」不是一个口号, 是这条军规的下半句54。
「接受度」的三个读数: 在用项目数、下载量、GitHub stars。书里给的道理 是需求侧的经济学:「需求越大,越可能被认可,这些数字越高,拿到成熟 经得起检验的软件的概率越大。」55
bus factor 为什么是「少信息分散=高风险」: 关键知识集中在越少人身上, 一旦出意外(书里那个不吉利的名字:巴士因子)团队越可能直接失去维护能力; 「如果创作者像个 one-man wrecking crew(单人拆楼队),那是项目暴露且 脆弱的明显信号——这种事常见到不能忽视。」56
语义化版本再敲一次: major(破坏性,高风险)、minor(新特性,中风险)、 patch(修 bug,低风险)——「版本号是最不可靠的采用度指标,升得多快全看 作者心情(当年浏览器还互相攀比版本号)」,但风险评估的分级是真的有用57。
迁移工具三选(diesel_migrations、refinery、migrant)——书里只列了名, 但位置说明了一切:它们和驱动、ORM 并列在「你会需要的周边」里。 数据库迁移不是 ORM 的一部分,是独立的一道工序(第 3、4 章会各见一次)58。
5.8 同题作文的评分细则(比行数更多的五个观察点)¶
宏展开行数(479/272/258)只是最扎眼的指标;书里同一段还埋了五个 评分维度,值得单列:59
- 元编程密度:Rocket 靠属性宏(
#[get]、#[post]、#[launch]) 替你生成 main 和路由收集;Axum 几乎全靠普通函数 + 提取器; Warp 干脆零宏。宏越多,源码越短、展开的真相越长; - 路由声明的重复度:Rocket 的
routes![index, greeting]与属性宏里 已写的路径是冗余的(「第 30 行的信息 16、21 行已经给过了」); - 启动函数的可见性:Rocket 文件里没有 main(
#[launch]生成); Actix/Axum/Tide 都显式写 async main——「Rust 程序不可能没有 main, 所以是宏替我们造了它」; - 错误通道的形状:Tide 的 handler 返回
Result(错误是一等公民); Axum 靠WithRejection包一层;Rocket 用 Responder 抽象—— 错误怎么流动,决定 handler 好不好读; - 示例的完整性:Tide 附了可跑的 curl(「这本该是标配」),其他家没有。
8. 主线例子再走一遍:反向 Hello World 的五次投胎¶
同一道题:POST /greeting 收 {"message":"hello"},回 {"acknowledged":"hello"},GET / 给用法
│
├─ Rocket:31 行源码,宏展开 479;#[launch] 造 main;路由收进 routes![...]
├─ Actix:结构同款,宏展开 272;HttpServer::new(|| App::new()...)
├─ Axum:Router::new().route(...);提取器 Json(greeting) 直接拆包;258 行
├─ Warp:get().and(path::end()).map(index) 零宏链式;
│ 类型长到 IDE 显示省略号
└─ Tide:async-std 血统;响应 builder 显式拼;唯一附 curl 示例
图说:五份答卷,同一张考卷;分差都在「宏替你藏了多少」上。
(行数为原书实测;端点与负载出自原书代码清单 2.1–2.9。)
这道题值得收藏的另一个原因:它已经是一个微 API 而非静态页—— 「收真实输入、产真实输出,像 REST API 那样工作」;而任何 Web 应用的 三个逻辑单元(数据定义、请求处理、bootstrap)在上面五个框架里都能 一一指出来60。
9. 前端选项的一次完整决策推演¶
把第 7 节的散点收束成一次选型会,问题按顺序问:
- 前端语言锁死了吗? 没有——任何前端最终都是 HTML/CSS/JS 静态文件, 后端只管托管;React/Vue/Angular/Svelte/Elm 全是合法选项61;
- 愿意离开 Rust 吗? 愿意 → JS/TS 管线(Webpack/Vite 打包, 框架随潮流);不愿意 → 走 Wasm;
- 走 Wasm,选哪个框架? Dioxus(类 React、到处跑)、 Yew(类 Angular 的完整框架)、Sycamore(响应式)—— 领域新到一切都在快速演化,「锁定任一都接受跟它一起进化」62;
- 样式怎么办? 纯手写 → 内联失控 → CSS → LESS/Sass(要转译) → Bootstrap/Foundation/UIKit/Tailwind(成套类)。
WebAssembly 的三句真相(原书注释级的事实): ① Wasm 不属于 Rust—— 写书时支持 14 种语言,任何能出二进制的编译器都行;② Wasm 救不了你不用 HTML/CSS——「前端应用可以由一颗 Rust 的心驱动,但皮还是那套」; ③ 浏览器 API(DOM 等)摸不着——必须留一层 JS 传话,工具链替你 藏住它,但管线里永远有它一步63。
10. 本卷小结:为什么「生态纵览」值一整章¶
第 2 章的选型论证到这里闭环:视角(02)立了尺子、打分表(03)给了流程、 本篇把候选全摆上桌(04)——数据库三视角给了「问什么」,六军规给了 「怎么挑」,五框架同题作文给了「长什么样」,REST/OpenAPI/GraphQL 给了 「对外说什么」,前端三选项给了「最外层怎么摆」。后面 12 章的每一个决定 (Axum、SeaORM、SQLite、Yew、Redis、Compose)都能在这一章找到它当年的 候选名单和被权衡掉的对手64。
11. 数据库纵览的完整决策树(把 §3 收成一条路)¶
第一步:数据规整吗?
├─ 不规整(字段随记录变)→ NoSQL 三选(键值/文档/图)
│ └─ 嵌套层级重、少跨类型关联 → 文档库(MongoDB 系)
│ └─ 只按键取、要极致快 → 键值库(Redis 系)
│ └─ 关系即查询(社交网络式) → 图库
└─ 规整 → 关系库
第二步:要多大程度可信?
├─ 单机构造 + 事务强一致(ACID) → PostgreSQL/MariaDB
└─ 分布式 → CAP 二选一(CP 关窗保真 / AP 旧数据保活)
└─ 再叠 BASE(最终一致)与 ACID 的事务轴对照
旁路:嵌入式零配置(测试/教学/单文件应用) → SQLite
旁路:缓存与消息中介(不是主存) → Redis(第 8/10 章返岗)
图说:先问数据形状,再问一致性胃口,最后才问产品 —— 顺序反了就是背名录。
关系度数的实现细节(多对多必须拆表):「项目经理能订阅多个事件、 事件有多个订阅者——直连不可行,拆成两条一对多,中间那张表叫 mapping」; 第 8 章的订阅集实现(Redis 集合 + 交集)正是这张映射表的内存版65。
12. 框架纵览的完整决策树¶
要宏魔法还是显式代码?
├─ 要(省样板优先) → Rocket(功能全、479 行展开;曾经「死而复生」)
├─ 不要 → 异步事件驱动?
│ ├─ 中庸 → Actix(actor 模型血统,272 行)
│ └─ Tokio 生态正中央 → Axum(258 行;「不为不用的付钱」;本书选择)
└─ 函数式链式? → Warp(零宏、类型即文档;IDE 之险自负)
或:保守显式 + async-std 血统 → Tide(快速撞限型)
图说:先选「愿意被框架藏住多少」,再选口味 —— 五个框架没有强弱,只有取向。
「20% 自称 simple」的数据背后的解读(再引一次):web 类 crate 里 自称 simple 的占 20%(全体 12%)——「simple 往往 simple 在缺功能」。 自称不算数,看清单:把你需要的功能列出来(Laravel 那张清单就是 模板),逐框打勾,缺口自己就会浮出来66。
13. 数据库话题的完整叙事(从「问什么」到「买哪个」)¶
本章数据库一节最值钱的不是产品名单,而是提问的顺序。书里刻意把 分类放在产品前面,就是怕读者拿着名单对号:先决定「从哪个视角看」, 每个视角只回答一类问题,三个视角都问完,候选圈已经缩到两三款, 产品对比才是最后一公里的细活。67
分布式视角问的是「出事时怎么办」: CAP 三保证里,一致性是「读到 最近写入」,可用性是「总有非错误应答」,分区容错是「断了也照转」。 真正要选的不是「三选二」——分区没得选——而是「断了之后,你要 关窗保真(CP)还是端旧数据保活(AP)」。书里那句判断很直白: 「想追求 CA 的,出于现实原因可以忽略」——凡是假装网络不会断的设计, 都不必进入下一轮。68
事务视角问的是「正确有多急」: ACID 把「正确」钉在「此刻」—— 事务要么整个成立、要么整个不算,并发等价于排队,提交后雷打不动; BASE 把「正确」放宽成「最终」——先答应读写、事后对账,「停止写入后 系统会自己收敛到一致」。一个订票系统和一个点赞计数器,分别站在这 条轴的两端;多数业务系统其实站在中间,按功能分域取舍。69
数据表示视角问的是「形状长什么样」: 关系库把数据拆进互相关联的 表,用键表达一对一、一对多、多对多——多对多必须拆出中间表,因为 「两边都是多,直连不可行」;NoSQL 三族各有自己的形状语言:键值库 只认键、文档库认层级、图库认连接。「数据不规整时,关系库的严格 表结构是负担」——这条贴士在第 11 章(动态 schema)会再一次以 「动态 schema vs schemaless」的面目出现。70
三个视角叠起来,产品名单就只是「按图索骥」:要事务强一致的开源 关系库——PostgreSQL/MariaDB;要嵌入式零配置——SQLite;文档要 JSON 自由——MongoDB;极致快键值兼消息中介——Redis。这份名单 的每一个名字,在后面章节都会真的登场:SQLite(第 3 章)被换掉、 MariaDB(第 4 章)接管主库、Redis(第 7/8/10 章)从 refresh token 缓存干到队列再到授权缓存、MongoDB(第 13 章)作为「换栈选项」 被重新介绍。第二章的名单不是名录,是全书的演员表。71
14. 框架纵览的完整叙事(为什么「同题作文」是公平的)¶
评测框架最容易踩的坑是「各写各的亮点」。书里强制同题作文—— 同一道题(反向 Hello World)、同一张考卷(POST JSON 进去、 JSON 出来、GET 给用法)、同一个裁判(宏展开行数、样板密度、 错误通道、示例完整度)——可比性是被题型设计出来的,不是 事后找补的。72
评分的重心也放得对:不是「谁的功能多」(五家都能收 JSON), 而是「谁替你藏的东西值得你信任」。Rocket 把 main 和路由 收集都藏进宏——方便,但 479 行展开里任何一行都可能藏着你的 bug; Axum 只藏底层(提取器、路由合并),handler 所见即所得—— 258 行,每一行你都见过。Warp 藏得最少,代价是类型签名长到 IDE 先投降;Tide 把错误通道摆到台面上(返回 Result), 「谨慎周到的做法」。「藏多少」没有标准答案,但「知道被藏了 什么」是选型者的基本修养——这句话是同题作文背后的真正考点。73
15. 本卷结语(为什么选型论证值三章)¶
02、03、04 三篇合起来回答了动工前的一切问题:这个词是什么意思(02 §3)、 这件事该按什么顺序想(02 §5–§6 + 03 §2–§4)、货架上有哪些货(04)。 后面十二章的每一个决定都能回溯到这三篇:Axum 出自五框架同题作文(04 §5)、 SQLite 与「可换性」出自产品地图(04 §3)、workspaces 分块出自模块化 视角(02 §5.6)、打分表在工单立项时真用了一次(03 §5.5)。选型论证 不是务虚,是把「后来的每一章」从「拍脑袋」变成「还账」——这是三篇 合卷时最该带走的一句话。74
16. 「反向 Hello World」作为面试题(本题的自荐用法)¶
把第 5 节的同题作文单独抽出来,它就是一道完美的框架面试题:「请用 你熟悉的框架实现:POST 收一个 JSON、记日志、回一个 JSON;GET 给用法。」 考察点全在评分细则里(§5.8):错误怎么走、路由怎么收、启动函数谁造的、 示例完整不完整——五分钟内能看出一个人与他的框架相处了多久。 原书用 31–41 行的小题讲透五个框架的脾气,这道题值得整个 Rust Web 社区共用。75
17. 本篇卷尾(一句话版)¶
数据库三视角管「问什么」,六军规管「怎么挑」,五框架同题作文管「长什么样」, REST/OpenAPI/GraphQL 管「对外说什么」,前端三选项管「最外层怎么摆」—— 货架到此摆完;全书的每一章,都从这张货架上取过货。76
18. 本篇卷尾补记(候选名单的日常用法)¶
本篇的每一张清单(数据库族谱、六军规、五框架、三 API 形态、三前端选项) 都适合在「接新需求」时重扫一遍:需求一变化,昨天的次优解可能就是今天的 正解(schemaless 需求来了?GraphQL 客户出现了?)。选型不是一次考试, 是持续的对账——这正是第 2 章「先需求后选型」纪律的复利。77
19. 本卷最后一页:四个「别」¶
读完 02–04 三篇,带走四个「别」:
- 别拿现成 stack 倒推需求——「先定义需求,再选组件」,顺序反了就是拍脑袋;
- 别给「架构」下定义——认领视角、声明位置,比争定义 productive 得多;
- 别用「simple」自我安慰——20% 自称 simple 的 web crate,「simple 往往 simple 在缺功能」;列清单打勾,缺口自己浮出来;
- 别为一时的需求形态过早签约——REST/GraphQL、JS 前端/Wasm,都等「真需要」再迁,这叫增量开发。78
20. 本篇卷尾补记(需求漂移时的回头路)¶
需求一漂移,就回到三视角重问:数据形状变了吗(表示视角)、一致性胃口 变了吗(事务视角)、出事容忍变了吗(分布式视角)。三问有变,候选名单 重扫;没变的,清单照旧——货架会旧,提问常新。79
21. 本篇卷尾补记(同题作文的复习法)¶
学任何新框架,先写这道「反向 Hello World」,再对照 04 篇的五份答卷: 你的写法像谁、差在哪、错误通道顺不顺——十分钟自测,胜过半天文档。80
-
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:846,搜「distinct layers」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:849,搜「lock-ins」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:864,搜「few different perspectives」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:870,搜「CAP theorem」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:895,搜「CP database」;:898,搜「AP database」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:902,搜「outdated information」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:908,搜「ACID」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:937,搜「Eventually consistent」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:952,搜「Many-to-many」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:959,搜「Key-value stores」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:978,搜「not uniform」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1007,搜「most used database」)、:1011(搜「leverage the benefit」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1020,搜「metrics」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1055,搜「mysql」;:1078,搜「SQLx」;:1089,搜「diesel_migrations」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1097,搜「KISS」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1103,搜「falls short」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1106,搜「20%」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1326,搜「Data definition」;:1332,搜「Bootstrap」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1115,搜「55 versions」;:1125,搜「Request guards」;:1137,搜「Fairings」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1305,搜「No main function」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1297,搜「479 lines」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1302,搜「Redundance」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1354,搜「actor model」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1477,搜「272 lines」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1483,搜「side-project」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1642,搜「258 lines」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1789,搜「poetical heights」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1805,搜「ellipses」)、:1808(搜「closing parenthesis」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1952,搜「test curl commands」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1817,搜「reach their limits」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1292,搜「Serde library」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1287,搜「DTOs」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1980,搜「not a standard」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1988,搜「application layer protocol」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:2013,搜「Swagger Specification」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:2043,搜「Linux Foundation」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1119,搜「Routing」)。本节五个框架的细节均出自原书 Backend frameworks overview 一节。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1119,搜「Routing」)、:1125(搜「Request guards」)、:1137(搜「Fairings」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1145,搜「Laravel」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1354,搜「actor model」)、:1477(搜「272 lines」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1483,搜「side-project」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1805,搜「ellipses」)、:1808(搜「closing parenthesis」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1952,搜「test curl commands」)、:1817(搜「reach their limits rapidly」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1970,搜「architecture style」)、:1980(搜「not a standard」)、:2000(搜「Statelessness」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:2013,搜「Swagger Specification」)、:2043(搜「Linux Foundation」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:2061,搜「Resource bundling」)、:2066(搜「Type definitions」)、:2075(搜「rarely needs them」)。 ↩↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:2090,搜「transpiled」)、:2100(搜「Webpack」)、:2105(搜「Vite」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:2128,搜「LESS」)、:2131(搜「Bootstrap」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:2165,搜「Dioxus」)、:2170(搜「Yew」)、:2173(搜「Sycamore」)、:2158(搜「evolve rapidly」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:888,搜「dooms strive for CA」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:912,搜「Atomicity」)、:915(搜「Consistency」)、:918(搜「Isolation」)、:921(搜「Durability」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:937,搜「restore consistency eventually」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:993,搜「PostgreSQL」)、:1001(搜「MongoDB」)、:1004(搜「Redis」)、:1007(搜「most used database」)、:1011(搜「leverage the benefit」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1024,搜「Fitness for the purpose」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1027,搜「Grade of acceptance」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1032,搜「bus factor」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1043,搜「least reliable marker」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1089,搜「diesel_migrations」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1297,搜「expanded to 479 lines」)、:1302(搜「Redundance」)、:1305(搜「No main function」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1319,搜「micro-API」)、:1326(搜「Data definition」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:2084,搜「plain old」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:2158,搜「evolve rapidly」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:2137,搜「sandbox」)、:2147(搜「14 different languages」)、:2177(搜「Rust heart」)。 ↩ -
本判断为我们的归纳:全章候选名单与各章落锤的对应关系,可逐条回核本章原文地图。 ↩
-
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:952,搜「Many-to-many」);订阅集实现见text/66-fm-implementing-the-pub-sub-system.txt:118。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1106,搜「20%」)。 ↩ -
分类先于产品的写法,见原书 Overview of database technologies 开头(
text/12-fm-the-architecture-frenzy.txt:864,搜「few different perspectives」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:888,搜「dooms strive for CA」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:908,搜「ACID」)、:937(搜「restore consistency eventually」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:978,搜「not uniform」)、:952(搜「Many-to-many」)。 ↩ -
演员表说法为我们的归纳;各产品登场章见对应拆解文档。 ↩
-
同题作文设计见原书 Backend frameworks overview 开头(
text/12-fm-the-architecture-frenzy.txt:1148,搜「reversed」)。 ↩ -
出处:「The architecture frenzy」(
text/12-fm-the-architecture-frenzy.txt:1297,搜「479 lines」)、:1642(搜「do not have to pay」)、:1952(搜「careful, considerate」)。 ↩ -
结语为我们的归纳;各对应关系见三篇原文地图。 ↩
-
面试题用法为我们的建议;题目与五份答卷见原书 Code listing 2.1–2.9。 ↩
-
卷尾为我们的归纳;五节分工见本篇目录。 ↩
-
补记为我们的用法建议;清单见本篇 §3–§7。 ↩
-
四「别」均为原书主张的整理;出处见本篇 §3(顺序)、§4(视角)、§5.6(20%)、
04§6.3(增量)。 ↩ -
回头路见本篇 §13 决策树;「选型是持续的对账」见本篇 §18。 ↩
-
复习法为我们的产品化建议;题目与答卷见本篇 §5、§8。 ↩