这一篇说明本卷怎么读、代码怎么跑、规模与成本的数字怎么理解。赶时间的读者可以只读「每章的结构」与「实验工程」两节。
这本书假设你已经知道什么
本卷假设读者具备以下基础:
- 能读懂 Go 代码,熟悉结构体、接口、错误处理与
context。 - 做过至少一个上线系统,知道发布、回滚、监控的基本流程。
- 理解服务拆分、数据库分片、缓存这些概念,不要求亲手实施过。
- 知道 SLO、错误预算、容量规划这些词,不要求能独立制定。
- 对成本有概念,知道计算、存储、带宽是分别计费的。
不要求读者做过单元化或多活。但也不打算从「什么是微服务」讲起。如果你完全没有规模化经验,建议先读第 1、2、6 章,再读案例章。
13 章的组织方式
本卷 13 章按「能力 → 案例 → 决策」排列:
- 单体到服务化:拆分的触发条件、按域拆还是按层拆、回退方案。
- 多活与容灾:单元化与用户路由、数据同步与冲突、切换回切与演练。
- 突发流量:热点特征、弹性扩容与预热、降级与排队。
- 数据规模:分库分表与路由、冷热分离与归档、迁移与双读。
- 成本治理:单位经济模型、存储与带宽成本、闲置回收与预算。
- 稳定性体系:SLO 与错误预算、故障分级与应急、复盘与改进闭环。
- 安全与合规:反爬与防刷、内容安全与未成年人保护、个人信息与审计。
- 研发效能:环境制品与流水线、内部平台边界、平台采纳与反悔成本。
- 演进案例 Feed:旧链路基线、双写灰度切换、结果与回退条件。
- 演进案例 IM:会话归属与路由、消息同步与顺序、切换演练与用户无感。
- 演进案例大促:容量规划与压测、限流降级预案、大促复盘。
- 决策与组织:团队边界与系统边界、决策权与评审、技术债与演进路线。
- 全书收口:从 MVP 到规模化的路线图、架构健康度自评、结语。
每一章的三节递进关系是:第一节给判定与模型,第二节给主实现与取舍,第三节处理失败、回切与边界。不建议只读第三节,因为失败场景依赖前两节的定义。
每章的结构
每章遵循相似结构:
- 问题开场:一次扩容、一次故障、一次评审争论。
- 判定与模型:把现象拆成边界、容量、成本、责任。
- 主实现:可运行的 Go 代码,配套测试与运行输出。
- 取舍与替代方案:至少两个备选方案,说明适用条件。
- 失败场景:一个具体故障,说明怎么发生、用户看到什么、怎么定位。
- 小结与边界:这一章不解决什么,留给哪一章。
「触发条件」和「退出条件」是每章都有的。如果某一章只讲「怎么做」而不讲「什么时候不该做」,那多半是写漏了。
实验工程
代码在 webapp-lab 实验工程里,module 名为 webapp,Go 版本 1.26.0。卷四的包按章划分:
webapp-lab/
go.mod
internal/
split/ # 第 1 章:拆分判定与回退
cell/ # 第 2 章:单元路由、同步、演练
burst/ # 第 3 章:突发识别、容量、降级
shard/ # 第 4 章:分片路由、切分、归档
cost/ # 第 5 章:单位成本、存储带宽、预算
slo/ # 第 6 章:SLO、故障分级、复盘
guard/ # 第 7 章:反爬、内容安全、PII
pipeline/ # 第 8 章:制品、平台边界、采纳
feedmig/ # 第 9 章:Feed 演进
immig/ # 第 10 章:IM 演进
promo/ # 第 11 章:大促容量与预案
org/ # 第 12 章:团队边界、决策、技术债
scalebase/ # 第 13 章:路线图、健康度、收口
每个包只依赖标准库,不引入第三方框架。原因是规模化的判断不该被框架藏起来:路由是否稳定、预算是否超支、SLO 是否烧完,都应该在代码里看清。
运行某一章:
go test ./internal/cell/ -count=1
go test ./internal/slo/ ./internal/cost/ -count=1
运行全卷:
go test ./... -count=1
代码块开头的三行标记:
// file: internal/cell/route.go
// tier: L1
// verify: go test ./internal/cell/
file 是路径,tier 是级别,verify 是验证命令。正文代码与工程文件逐字节一致。
代码分级
| 级别 | 含义 | 依赖 | 本卷情况 |
|---|---|---|---|
| L1 | 单包纯逻辑 | 仅标准库 | 第 1–13 章 |
| L2 | 进程内端到端 | httptest、内存适配器 | 本卷不做 |
| L3 | 真依赖 | 数据库、缓存、消息 | 本卷不做 |
| L4 | 多节点、故障注入 | 容器、网络工具 | 本卷不做 |
本卷刻意停在 L1。单元化、多活、故障演练的真实行为高度依赖网络、时钟与存储,书里的纯函数只能验证「判定逻辑是否正确」,不能替代真实环境。读者要把代码用于生产,至少需要补上真实路由、真实同步与真实演练。
L1 的价值在于:它把「什么条件下该切」「什么条件下该退」写成可测试的代码。这些判定即使换成 Java 或 Rust,逻辑也一样。
规模与成本口径
规模化讨论里,数字比定义更容易出问题。本卷统一约定:
- 日活、订单、QPS、成本等案例数字,一律标注「案例假设值」。
- 容量用「峰值 QPS × 安全系数」表达,安全系数写明是 1.3 还是 1.5。
- 成本统一用「分」或「元/月」,币种写清;带宽按 GB 计,不按 GBps。
- 存储容量按 GB 计,1 TB = 1024 GB;保留期按天计。
- 百分比一律写清分母,例如「发布冲突率 = 有冲突的发布次数 / 总发布次数」。
本书对数字的使用有三条规则:
- 实测就是实测。 标注「实测」的输出,都在本机真实执行过,命令和结果一起给出。
- 示例就是示例。 容量、成本、延迟都是案例假设,不代表真实业务。
- 预期就是预期。 没有跑过的结果,写「预期」「应当」,不写「实测」。
三种读法
按能力读。 第 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 章。回答「规模化需要哪些能力」。适合正在做架构升级的团队。
按案例读。 第 9 → 10 → 11 章。回答「一次真实演进会踩哪些坑」。适合已经决定要改、需要具体方案的人。
按决策读。 第 12 → 13 章。回答「谁来决定、什么时候做、什么时候停」。适合技术负责人与评审者。
每章独立,包也独立,但建议至少先读第 1、2 章,因为后面的章节会反复引用拆分与单元化。
怎么判断自己读懂了
每章末尾有「小结与边界」。读完一章,试着回答:
- 这个方案的触发条件是什么?不满足时会怎样?
- 这个方案怎么回退?回退需要谁配合、多长时间?
- 这个数字的分母、窗口、负责人分别是什么?
三个问题都能用自己的话回答,并且能指出代码里对应的函数,才算读懂。只记住「做了单元化」「上了 SLO」不算。
与站内其他内容的关系
站内已有服务拆分、高可用、容量、成本、SLO、混沌工程相关的文章。本卷不复述它们的定义与清单,只在需要时用一段话交代结论并给出链接。
本卷新增的是三样东西:
- 把能力放回「回声」的具体阶段,说明为什么现在做、不现在做会怎样。
- 每一节都有可运行的 Go 代码和真实输出。
- 每一节都有一个失败场景,说明做错了用户、财务或运维会看到什么。
已知的取舍
写这本卷时,我刻意做了一些取舍:
- 不写云厂商选型。 成本章节给计算方法,不给采购建议。
- 不写 Kubernetes 部署细节。 这些属于运维手册。
- 不写完整安全攻防。 只写与业务架构相关的边界。
- 不写组织管理理论。 只写与系统边界直接相关的团队边界与决策权。
- 不写多活的全量实现。 只写路由、同步、演练三个判定点。
如果读者需要这些内容,站内有对应专题,本书会在相关章节给出入口。
环境准备
实验工程只依赖 Go 标准库。准备 Go 1.26.0:
go version
# go version go1.26.0 darwin/arm64
进入工程后先跑全量测试:
go test ./... -count=1
第一次编译稍慢,之后单包测试通常在几百毫秒内完成。正文输出均来自本机 -count=1 的结果。
命名与错误处理约定
为了让跨章阅读一致,本书遵循几条约定:
- 容量、成本、延迟字段带单位后缀,例如
QPS、Cents、Ms。 - 状态与级别用字符串枚举,判定函数返回
error,不 panic。 - 参数错误、策略拒绝、系统失败分开表达;参数错误不重试,策略拒绝不告警,系统失败才重试。
- 判定函数尽量纯:输入结构体,输出判定与原因,不读写全局状态。
- 排序函数保持稳定,便于测试与复现。
这些约定是为了让读者能快速看出「这段代码在防什么」。读者可以用别的风格,但建议保留「判定与原因一起返回」这一条。
代码阅读顺序
正文里的代码块通常只展示一个文件的核心部分,完整文件在实验工程里。建议按下面的顺序读:
- 先看类型定义。字段决定了模型能表达什么。
- 再看判定函数。它决定这一节的核心结论。
- 最后看测试。测试用例是行为契约,比注释更准确。
如果时间有限,可以只读类型定义和测试。类型定义告诉你「系统认为有哪些东西」,测试告诉你「这些在什么情况下应该怎样」。
表格怎么读
本书的表格分三类:
- 对比表:多个方案在若干维度上的差异。先看自己的约束落在哪一列。
- 参数表:阈值、默认值、单位。这些是起点,不是结论。
- 判定表:条件、动作、后果。读的时候检查「有没有条件没有对应动作」。
表格里的示例数字会在表前或表后注明。没有注明的阈值,通常是代码里的默认值,可以在实验工程里找到对应常量。
三个常见误解
误解一:规模化就是拆分。 拆分只是手段之一。有些系统保持模块化单体,靠垂直扩容与读写分离就能撑很久;有些系统拆了很多服务,边界仍然混乱,故障反而更多。判断标准不是服务数量,而是「发布是否更独立、故障是否更局部、成本是否更可控」。
误解二:多活就是高可用。 多活解决的是地域级故障,但会引入数据同步、路由与回切问题。单地域内没有做好隔离与容量,多活只是把故障从一个机房搬到两个机房。第 2 章会先讲单元内的边界,再讲跨单元切换。
误解三:成本优化就是砍机器。 砍机器最快,但也最容易把稳定性砍掉。真正的成本治理先看单位经济模型:每订单成本、每 GB 成本、每万次请求成本。找到成本结构里最不合理的那一项,再决定是优化、迁移还是下线。
误解四:架构演进可以一次做完。 规模化是一个持续过程,业务在变、流量在变、团队在变。一次「大改造」往往在半年后就与新业务不匹配。本卷更推荐小步演进:每步有触发条件、有验收、有回退,而不是等积重难返再做整体重构。
这四个误解的共同点是:把手段当目标。本卷每一章都会先问「要解决哪个具体问题」,再给方案。
还有一个更隐蔽的误解:把「别人这么做」当成理由。别家的规模、团队、成本结构与你不同,同一个方案在别处成立,在这里未必。读案例章时,重点看它的约束与代价,而不是结论。
反馈与勘误
书中的代码都在实验工程里,读者可以直接改、直接跑。如果发现某段代码跑不通,或者某个结论与你的经验不符,欢迎指出。特别是「实测」类内容,如果你的环境和书里差很多,那很可能是我漏写了某个前提。
对于示例数字,不必纠结具体值,关注比例关系即可。对于阈值建议,把它当作起点,用自己的数据重新标定。
致谢
感谢在写作过程中提供扩容事故、成本账单与评审意见的同事。书里的失败场景大多来自真实事故的抽象,细节做了改写,但故障模式没有编造。
也感谢前三卷的读者,他们对「触发条件」「退出条件」的反馈直接影响了本卷的写法。
如果这本书只能留下一个习惯,我希望是:每次提出一个规模化方案之前,先写一句「它解决哪个具体问题、怎么验证、怎么退」,再动手。
这句话看起来像流程要求,其实是成本最低的自我约束。大部分失败的改造,不是技术选错,而是从一开始就没说清要解决什么;做到一半发现方向不对,又因为没有回退方案而只能继续加码。
写作过程中我也用这句话检查每一章:如果某一节说不出「不做会怎样」,就说明它还没想清楚,需要重写。
最后,感谢每一位愿意在评审会上说「这个方案怎么退」的同事。这句话不讨喜,但它救过很多项目。
写作时我也常提醒自己:书里的方案都有前提,别把某一条当成通用答案。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。