《互联网产品的服务端架构·规模化与架构演进》前言

卷四前言:说明读者假设、13 章的组织方式、每章的统一结构、可运行 Go 实验工程的包划分、代码分级、规模与成本口径、三种阅读路径、代码阅读顺序、表格读法与退出条件,以及如何判断自己真的读懂了规模化决策;文中 Go 代码均可在本地逐字节复现。

这一篇说明本卷怎么读、代码怎么跑、规模与成本的数字怎么理解。赶时间的读者可以只读「每章的结构」与「实验工程」两节。

这本书假设你已经知道什么

本卷假设读者具备以下基础:

  • 能读懂 Go 代码,熟悉结构体、接口、错误处理与 context。
  • 做过至少一个上线系统,知道发布、回滚、监控的基本流程。
  • 理解服务拆分、数据库分片、缓存这些概念,不要求亲手实施过。
  • 知道 SLO、错误预算、容量规划这些词,不要求能独立制定。
  • 对成本有概念,知道计算、存储、带宽是分别计费的。

不要求读者做过单元化或多活。但也不打算从「什么是微服务」讲起。如果你完全没有规模化经验,建议先读第 1、2、6 章,再读案例章。

13 章的组织方式

本卷 13 章按「能力 → 案例 → 决策」排列:

  1. 单体到服务化:拆分的触发条件、按域拆还是按层拆、回退方案。
  2. 多活与容灾:单元化与用户路由、数据同步与冲突、切换回切与演练。
  3. 突发流量:热点特征、弹性扩容与预热、降级与排队。
  4. 数据规模:分库分表与路由、冷热分离与归档、迁移与双读。
  5. 成本治理:单位经济模型、存储与带宽成本、闲置回收与预算。
  6. 稳定性体系:SLO 与错误预算、故障分级与应急、复盘与改进闭环。
  7. 安全与合规:反爬与防刷、内容安全与未成年人保护、个人信息与审计。
  8. 研发效能:环境制品与流水线、内部平台边界、平台采纳与反悔成本。
  9. 演进案例 Feed:旧链路基线、双写灰度切换、结果与回退条件。
  10. 演进案例 IM:会话归属与路由、消息同步与顺序、切换演练与用户无感。
  11. 演进案例大促:容量规划与压测、限流降级预案、大促复盘。
  12. 决策与组织:团队边界与系统边界、决策权与评审、技术债与演进路线。
  13. 全书收口:从 MVP 到规模化的路线图、架构健康度自评、结语。

每一章的三节递进关系是:第一节给判定与模型,第二节给主实现与取舍,第三节处理失败、回切与边界。不建议只读第三节,因为失败场景依赖前两节的定义。

每章的结构

每章遵循相似结构:

  1. 问题开场:一次扩容、一次故障、一次评审争论。
  2. 判定与模型:把现象拆成边界、容量、成本、责任。
  3. 主实现:可运行的 Go 代码,配套测试与运行输出。
  4. 取舍与替代方案:至少两个备选方案,说明适用条件。
  5. 失败场景:一个具体故障,说明怎么发生、用户看到什么、怎么定位。
  6. 小结与边界:这一章不解决什么,留给哪一章。

「触发条件」和「退出条件」是每章都有的。如果某一章只讲「怎么做」而不讲「什么时候不该做」,那多半是写漏了。

实验工程

代码在 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. 预期就是预期。 没有跑过的结果,写「预期」「应当」,不写「实测」。

三种读法

按能力读。 第 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 章。回答「规模化需要哪些能力」。适合正在做架构升级的团队。

按案例读。 第 9 → 10 → 11 章。回答「一次真实演进会踩哪些坑」。适合已经决定要改、需要具体方案的人。

按决策读。 第 12 → 13 章。回答「谁来决定、什么时候做、什么时候停」。适合技术负责人与评审者。

每章独立,包也独立,但建议至少先读第 1、2 章,因为后面的章节会反复引用拆分与单元化。

怎么判断自己读懂了

每章末尾有「小结与边界」。读完一章,试着回答:

  1. 这个方案的触发条件是什么?不满足时会怎样?
  2. 这个方案怎么回退?回退需要谁配合、多长时间?
  3. 这个数字的分母、窗口、负责人分别是什么?

三个问题都能用自己的话回答,并且能指出代码里对应的函数,才算读懂。只记住「做了单元化」「上了 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。
  • 参数错误、策略拒绝、系统失败分开表达;参数错误不重试,策略拒绝不告警,系统失败才重试。
  • 判定函数尽量纯:输入结构体,输出判定与原因,不读写全局状态。
  • 排序函数保持稳定,便于测试与复现。

这些约定是为了让读者能快速看出「这段代码在防什么」。读者可以用别的风格,但建议保留「判定与原因一起返回」这一条。

代码阅读顺序

正文里的代码块通常只展示一个文件的核心部分,完整文件在实验工程里。建议按下面的顺序读:

  1. 先看类型定义。字段决定了模型能表达什么。
  2. 再看判定函数。它决定这一节的核心结论。
  3. 最后看测试。测试用例是行为契约,比注释更准确。

如果时间有限,可以只读类型定义和测试。类型定义告诉你「系统认为有哪些东西」,测试告诉你「这些在什么情况下应该怎样」。

表格怎么读

本书的表格分三类:

  • 对比表:多个方案在若干维度上的差异。先看自己的约束落在哪一列。
  • 参数表:阈值、默认值、单位。这些是起点,不是结论。
  • 判定表:条件、动作、后果。读的时候检查「有没有条件没有对应动作」。

表格里的示例数字会在表前或表后注明。没有注明的阈值,通常是代码里的默认值,可以在实验工程里找到对应常量。

三个常见误解

误解一:规模化就是拆分。 拆分只是手段之一。有些系统保持模块化单体,靠垂直扩容与读写分离就能撑很久;有些系统拆了很多服务,边界仍然混乱,故障反而更多。判断标准不是服务数量,而是「发布是否更独立、故障是否更局部、成本是否更可控」。

误解二:多活就是高可用。 多活解决的是地域级故障,但会引入数据同步、路由与回切问题。单地域内没有做好隔离与容量,多活只是把故障从一个机房搬到两个机房。第 2 章会先讲单元内的边界,再讲跨单元切换。

误解三:成本优化就是砍机器。 砍机器最快,但也最容易把稳定性砍掉。真正的成本治理先看单位经济模型:每订单成本、每 GB 成本、每万次请求成本。找到成本结构里最不合理的那一项,再决定是优化、迁移还是下线。

误解四:架构演进可以一次做完。 规模化是一个持续过程,业务在变、流量在变、团队在变。一次「大改造」往往在半年后就与新业务不匹配。本卷更推荐小步演进:每步有触发条件、有验收、有回退,而不是等积重难返再做整体重构。

这四个误解的共同点是:把手段当目标。本卷每一章都会先问「要解决哪个具体问题」,再给方案。

还有一个更隐蔽的误解:把「别人这么做」当成理由。别家的规模、团队、成本结构与你不同,同一个方案在别处成立,在这里未必。读案例章时,重点看它的约束与代价,而不是结论。

反馈与勘误

书中的代码都在实验工程里,读者可以直接改、直接跑。如果发现某段代码跑不通,或者某个结论与你的经验不符,欢迎指出。特别是「实测」类内容,如果你的环境和书里差很多,那很可能是我漏写了某个前提。

对于示例数字,不必纠结具体值,关注比例关系即可。对于阈值建议,把它当作起点,用自己的数据重新标定。

致谢

感谢在写作过程中提供扩容事故、成本账单与评审意见的同事。书里的失败场景大多来自真实事故的抽象,细节做了改写,但故障模式没有编造。

也感谢前三卷的读者,他们对「触发条件」「退出条件」的反馈直接影响了本卷的写法。

如果这本书只能留下一个习惯,我希望是:每次提出一个规模化方案之前,先写一句「它解决哪个具体问题、怎么验证、怎么退」,再动手。

这句话看起来像流程要求,其实是成本最低的自我约束。大部分失败的改造,不是技术选错,而是从一开始就没说清要解决什么;做到一半发现方向不对,又因为没有回退方案而只能继续加码。

写作过程中我也用这句话检查每一章:如果某一节说不出「不做会怎样」,就说明它还没想清楚,需要重写。

最后,感谢每一位愿意在评审会上说「这个方案怎么退」的同事。这句话不讨喜,但它救过很多项目。

写作时我也常提醒自己:书里的方案都有前提,别把某一条当成通用答案。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「books」更多文章

  1. 《互联网产品的 AI 架构·平台化与治理》附录 C 平台化评审清单
  2. 《互联网产品的 AI 架构·平台化与治理》附录 B 能力目录与配额字段速查
  3. 《互联网产品的 AI 架构·平台化与治理》附录 A 治理角色与职责速查