本卷要解决的问题
卷一不教 Go 语法,也不教某个框架的安装。它回答一个更靠前的问题:当一个互联网产品从想法走到百万日活,服务端应该在什么时刻、因为什么理由、长成什么形状?
具体拆成四件事:
- 把产品语言翻译成服务端可计算的约束,而不是直接翻译成中间件清单;
- 把账号、资料、多端接入这些“每个产品都要有”的基础能力,写成有边界、有失败语义的模块;
- 把流量入口、读写路径、异步、发布、观测、容量这些横切问题,放进同一个产品阶段里讨论;
- 用一个贯穿项目
webapp-lab走完从产品事实到可运行基线的完整链路。
卷二处理内容、社交与实时互动,卷三处理交易、增长与平台化,卷四处理规模化与架构演进。本卷遇到这些题目时只划边界,不展开实现。
全书结构:13 章分四段
| 段落 | 章节 | 回答的问题 | 本段产出 |
|---|---|---|---|
| 一、约束与表达 | 第 1–2 章 | 产品事实如何变成服务端形状?决策怎么写得可评审? | 四种形状分类器、容量与 SLO 模型、一份 ADR |
| 二、身份与入口 | 第 3–7 章 | 用户是谁、从哪个端来、请求从哪里进? | 账号会话模型、资料可见性规则、BFF 契约、网关边界 |
| 三、读写与协作 | 第 8–10 章 | 读多写少怎么接住?异步边界在哪?怎么安全上线? | 缓存决策卡、异步责任表、灰度与回滚方案 |
| 四、运行与收口 | 第 11–13 章 | 出事怎么定位?容量和成本怎么算?基线怎么交付? | SLI 清单、容量模型、可运行的账号 + 资料 + BFF 基线 |
13 章不是 13 个孤立专题。每一章都往 webapp-lab 里加一层可运行或可检查的产物,最后一章把这些产物串成一条端到端用例。
章节依赖图
第 1 章 产品约束
│
├──► 第 2 章 从需求到架构(用例 / 领域 / ADR)
│ │
│ └──► 第 13 章 收口(模块划分 / 端到端 / 基线)
│
├──► 第 3 章 账号与身份
│ │
│ └──► 第 4 章 资料与隐私
│ │
│ └──► 第 5 章 多端与 BFF
│
├──► 第 6 章 产品化 API
│ │
│ └──► 第 7 章 流量入口
│
├──► 第 8 章 读写与缓存
│
├──► 第 9 章 异步与消息
│
├──► 第 10 章 发布与灰度
│
└──► 第 11 章 可观测性 ──► 第 12 章 容量与成本
│
└──► 第 13 章 收口
这张图只表达“先读什么更顺”,不是硬依赖。第 6 章可以在第 3 章之前读;第 11 章可以独立读;第 13 章必须放在第 2、3、5 章之后,因为它要把这些产物装配起来。
三条阅读路径
| 路径 | 适合谁 | 顺序 | 预计产出 |
|---|---|---|---|
| 产品转架构 | 产品经理、技术负责人 | 1 → 2 → 5 → 6 → 9 → 12 | 一份能评审的架构约束清单 |
| 后端补产品 | 有后端经验、第一次负责完整产品域 | 3 → 4 → 5 → 7 → 8 → 11 | 账号到 BFF 的可运行基线 |
| 面试与复盘 | 准备系统设计面试或事故复盘 | 1 → 8 → 9 → 11 → 12 | 一套从症状到章节的定位方法 |
不建议从第 3 章直接跳到第 13 章。第 13 章的模块划分依赖第 2 章的边界和第 5 章的 BFF 契约,跳读会看到一堆没有来源的结论。
贯穿案例的三个阶段
「回声」不是一次性设计出来的。本书把它分成三个阶段,每章都会说明结论适用于哪个阶段,避免把千万级方案搬进只有十万用户的系统:
| 阶段 | 规模假设 | 主要矛盾 | 典型动作 |
|---|---|---|---|
| 起步 | 10 万 DAU | 活下来、快速验证 | 单体、单库、少量缓存,先保证可观测 |
| 增长 | 100 万 DAU | 热点、峰值与故障半径 | 读写分离、异步化、灰度、容量余量 |
| 规模 | 1000 万 DAU | 成本、组织与演进速度 | 分片、单元化、平台化、预算机制 |
阶段之间没有清晰的分界线,触发条件比数字更重要。一个常见的触发条件是“同一类故障一个月内出现两次”,它通常比 DAU 到达某个整数更能说明系统需要改变。
书中反复使用一个判断:当前阶段最简单、但知道风险在哪的方案,优于提前三年落地、团队维护不起的方案。 这不是反对演进,而是要求每次演进都有触发条件、回退方案和可验证的结果。
十三章速览
第 1 章 产品约束
从「回声」的三个产品事实出发,说明服务端分类为什么按实时、强一致、读写比、写多的优先级展开;再把用户量、请求量与成本换算成可追溯的假设,最后把可用性、体验与合规写成可计算的底线。
产出:四种形状分类器、容量模型、SLO 与 burn rate 计算。
第 2 章 从需求到架构
把产品需求拆成用例与用户旅程,画出系统边界;再从领域模型推导数据所有权;最后把关键取舍写成一份带备选方案和后果的架构决策记录。
产出:用例清单、上下文边界、ADR-001。
第 3 章 账号与身份
讨论注册登录、第三方身份、会话与设备、多端互踢,以及撞库、风控和账号找回。重点不是登录页,而是“谁在什么设备上以什么身份操作”的会话模型。
产出:会话状态机、多端互踢规则、账号安全阈值表。
第 4 章 资料与隐私
把用户资料拆成公开、好友可见、仅自己可见三类字段,讨论个人信息分级、最小化采集、注销、导出与数据留存。
产出:字段可见性矩阵、注销流程与留存期限。
第 5 章 多端与 BFF
比较 App、Web、小程序在登录态、网络、包体和交互上的差异,说明 BFF 为什么不是“再加一个网关”,而是按端聚合与裁剪的契约层。
产出:三端能力矩阵、BFF 聚合契约、端上体验的取舍清单。
第 6 章 产品化 API
从资源与命令的语义差异讲起,讨论错误码如何让用户看懂失败,最后处理版本演进与兼容窗口。
产出:API 语义表、错误码分层、兼容性检查清单。
第 7 章 流量入口
区分静态与动态请求,讨论 CDN、网关与边缘的职责边界,重点讲认证、路由、限流和回源保护。
产出:入口链路图、网关职责表、回源保护策略。
第 8 章 读写与缓存
从读多写少的产品事实出发,讨论缓存位置、一致性窗口和热点失效,重点不是缓存中间件,而是“哪个读路径可以容忍多旧的数据”。
产出:读路径分级表、缓存决策卡、热 key 预案。
第 9 章 异步与消息
判断哪些事情不该阻塞用户,区分事件、通知与最终一致的语义,最后处理重复、丢失与补偿在用户侧的表现。
产出:异步责任表、消息语义对照、补偿与对账清单。
第 10 章 发布与灰度
把功能上线拆成最小发布单元,讨论灰度、开关与回滚,以及数据兼容与双写窗口。
产出:发布检查清单、灰度比例表、回滚触发条件。
第 11 章 可观测性
从用户投诉出发定义 SLI,讨论日志、指标与追踪的最小集合,再用一次线上问题复盘演示定位过程。
产出:SLI 清单、最小观测契约、复盘模板。
第 12 章 容量与成本
把 DAU 换算成 QPS、并发与副本数,再算存储、带宽与机器成本,最后讨论容量余量与弹性策略。
产出:容量模型、成本拆分表、弹性与预算规则。
第 13 章 收口
把账号、资料与 BFF 装配成一条端到端用例,跑通测试,给出基线指标,并交接给卷二。
产出:可运行基线、端到端测试、卷二手接清单。
webapp-lab 的代码分级
本书所有代码都来自同一个 Go 实验工程 webapp-lab(模块名 webapp,Go 1.26.0)。文章里的代码块与工程文件逐字节一致,避免“书里能跑、复制下来不能跑”。
| 级别 | 判定 | 验收 |
|---|---|---|
| L1 | 纯逻辑或单包,不依赖外部进程 | gofmt -l 无输出、go vet、go test,并发包加 -race |
| L2 | 进程内端到端,httptest 或本机端口,内存适配器 | 一个脚本跑通产品用例并断言状态 |
| L3 | 真依赖:Docker Compose + PostgreSQL 18.4(Redis 可选) | 固定场景脚本与原始输出,只写实际跑过的数字 |
| L4 | 多节点、故障注入、网络分区 | 本卷不做;相关结论明确标注“需真实环境” |
卷一的目标是:全部章节至少 L1;账号、资料与 BFF 有一条 L2 用例;至少一次 PostgreSQL L3 端到端。
数字口径
「回声」是一个为本书构造的假想产品。书中出现的 DAU、QPS、延迟、成本和比例,除非明确标注“运行输出”,否则都是案例假设值,用来演示推导过程,不是任何真实系统的实测。
这样处理有两个原因:真实生产数据不能公开;而编造一个“实测”数字比写一个假设值更有害,因为它会让读者以为结论可以直接复用。每当你看到数字,先问三个问题:
- 这个数字来自产品指标、压测,还是作者假设?
- 它对应的窗口和口径是什么?
- 如果它错一倍,结论会不会翻转?
与已有书稿的关系
本站已有《后端架构设计》四卷,讲通用架构方法论与 arch-lab 订单系统;也有《游戏服务端架构》四卷,讲游戏品类的状态、时间、连接与权威。本书不重复这两套书的方法论,只写它们没有回答的问题:互联网产品的产品形态,如何决定服务端的读写路径、数据模型与容量结构。
遇到缓存、限流、分布式事务、多活等机制细节时,正文只给判断与取舍,具体实现用站内链接指回已有文章。
本卷不覆盖的内容
明确边界比罗列目录更重要。以下题目本卷只提判断,不展开实现:
- 具体框架与中间件安装。Redis、Kafka、PostgreSQL 的部署参数属于运维与中间件书稿,本卷只讨论“为什么需要它、放在哪一层”。
- 前端与客户端实现。BFF 会讲契约与裁剪,但不讲 React、Swift、小程序的具体写法。
- 推荐与搜索的算法。卷二只讲业务服务与推荐/搜索服务的边界、索引同步和冷启动兜底,不推导排序模型。
- 多节点容灾的实操。卷四会讲拓扑与演练设计,但本书不做真实多机房部署,相关结论必须标注“需真实环境验证”。
- 组织与商业决策。团队拓扑只讲与系统边界相关的部分,不展开绩效考核、定价与增长策略。
如果你需要的是某套框架的入门,本站已有对应的语言与框架书稿;本书的定位是把产品问题翻译成架构约束。
术语约定
同一批词在不同团队里含义不同,先约定本书的用法:
| 术语 | 本书含义 | 容易混淆的说法 |
|---|---|---|
| 产品形状 | 由产品事实推导出的服务端分类(读多、写多、实时、事务) | “业务类型”“行业” |
| 读路径 | 一次用户读取经过的服务与缓存链路 | 单个接口 |
| 写路径 | 一次用户写入经过的事务、消息与存储链路 | 单个 SQL |
| 一致性窗口 | 用户可能读到旧数据的最大时间 | “最终一致”四个字 |
| 降级 | 主动关闭非核心功能以保住核心链路 | 故障后的被动不可用 |
| 容量 | 在目标延迟与利用率下能承载的请求量 | 机器数量 |
| 基线 | 可重复运行、可比较的一组指标与用例 | 某次压测的最高值 |
术语不是文字游戏。评审时如果两个人对“降级”的理解不同,一个以为是有序关闭,一个以为是服务挂了,结论就会完全不同。
如何判断自己读懂了
每章结尾都有“小结”和“常见错误与边界”。如果你能不看正文回答下面五个问题,说明这一章已经读完:
- 这一章解决的产品问题是什么?如果产品阶段变了,结论会怎么变?
- 本章的决策依赖哪些假设?假设错一倍,结论会不会翻转?
- 失败时用户看到什么?服务端看到什么?两者是否一致?
- 哪些能力是现在就必须有的,哪些可以等到下一个量级?
- 如果要把这一章的结论写进 ADR,备选方案和回退条件是什么?
回答不了第 2 题,通常意味着把案例数字当成了结论;回答不了第 5 题,通常意味着还没有真正做取舍。
常见误区
- 把“产品形态”理解成行业标签。同样是内容社区,图文、短视频、直播的服务端形状完全不同。
- 先选中间件再找理由。正确的顺序是先写产品事实,再让事实决定需要哪些能力。
- 把假设数字当结论。案例数字只用于演示推导,不能直接搬进容量规划。
- 只读第 1 章就开始拆服务。分类告诉你风险,不告诉你部署单元。
- 跳过第 11、12 章直接做业务。没有观测和容量口径,业务上线后无法判断是否真的成功。
小结
卷一的目标不是给你一套标准架构,而是给你一套把产品语言翻译成服务端约束的方法。读完你应该能回答:这个产品最可能以什么方式坏?为了接住它,最少需要哪些能力?这些能力在当前的用户量和团队规模下,值得花多少成本?
带着这三个问题进入第 1 章。
下一步
如果你只有一小时,建议按下面的顺序读:
- 先读 1.1,拿到“实时 > 强一致 > 读写比 > 写多”的分类顺序;
- 再读 1.2,把「回声」的假设数字亲手算一遍,看看哪个假设最敏感;
- 最后读 1.3,把可用性换算成 30 天的分钟数,再决定你的产品配得上哪个 9。
如果你正在为一个真实产品做架构评审,直接跳到第 2 章和第 13 章,先看决策记录和基线是怎么收口的,再回头补前面的章节。
无论走哪条路径,都不要跳过“运行一遍代码”这一步。本书的结论都可以被测试或计算验证,读懂了但跑不出来,通常意味着某个假设还没有真正理解。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。