80.3 架构设计文档模板
一句话
架构文档不是 “写作文”,而是按评审会要问的顺序把问题答完:一份回答 “为什么是它”(选型),一份回答 “具体怎么做”(设计);两份分开写,评审才能在 1 小时内给出结论,而不是听完 1 小时汇报后说 “再想想”。
两份文档,两拨读者
| 文档 | 要回答的问题 | 读者 | 合理长度 |
|---|---|---|---|
| 备选方案(选型文档) | 为什么是它?为什么不选另外两个? | 决策者:技术委员会、业务负责人 | 5–15 页 |
| 架构设计(设计文档) | 具体怎么做、怎么落地、怎么回滚? | 执行者:开发、运维、DBA、测试 | 20–50 页 |
把两份合成一份,必然出现 “决策者嫌啰嗦、执行者嫌没细节”;拆开写的成本只是多一次目录,收益是两边都读得下去。
备选方案:五章
| 章 | 写什么 | 最常见的缺陷 |
|---|---|---|
| ① 需求介绍 | 背景、目标、范围(明确不做什么) | 只写目标,不写边界,评审时才发现对 “做什么” 理解不同 |
| ② 需求分析 | 5W1H + 8C,NFR 全部落到数字 | 只有功能描述,没有 P99 / 吞吐 / 可用性 |
| ③ 复杂度分析 | 高可用、高性能、可扩展各一句 “本方案的主要矛盾是 X” | 三条都写 “非常重要”,等于没说 |
| ④ 备选方案 | 至少 3 个,每个都有架构图 + 关键设计点 | 只写自己想推的那一个 |
| ⑤ 方案评估 | 360 度环评:对 8C 逐项写 “满足 / 不满足 / 代价” | 用 “更好、更快” 代替逐项对比 |
5W1H 与 8C:把 “需求” 变成可评估的维度
| 维度 | 问什么 |
|---|---|
| Who | 谁用?内部用户、外部 C 端、还是系统间调用 |
| When | 什么时候用?峰值在何时、持续多久 |
| What | 做什么?核心用例 3–5 个 |
| Where | 在哪跑?单机房 / 多地域 / 边缘 |
| Why | 为什么现在做?不做会怎样 |
| How | 关键业务流程(一张时序图) |
8C 是评估备选方案的打分维度,每一项都要能写 “满足 / 不满足 / 代价是什么”:
| 维度 | 典型问题 |
|---|---|
| 性能 | P99、峰值吞吐、容量上限 |
| 成本 | 三年 TCO(机器 + 人力 + 迁移) |
| 时间 | 多久能上线?会不会影响已有排期 |
| 可靠性 | 可用性几个 9、RPO/RTO |
| 安全性 | 认证授权、数据分级、攻击面 |
| 合规性 | 等保、数据出境、审计留痕 |
| 技术性 | 团队会不会、社区活不活跃、能否招到人 |
| 兼容性 | 与现有系统、协议、数据格式的兼容成本 |
⚠️ 最容易漏的是 成本 和 合规性:评审现场被问 “三年多少钱” 或 “数据能不能出境” 时答不上来,方案会当场被打回。
架构设计:六章
| 章 | 写什么 | 验收标准 |
|---|---|---|
| ① 总体方案 | 一段话说清整体思路 + 一张总图 | 不看后文也能知道这套系统长什么样 |
| ② 架构总览 | 架构图 + 每个模块一句职责 + 关键设计点(3–5 条) | 图上每个方块在正文都有对应描述 |
| ③ 核心流程 | 3–5 条主链路的时序图(下单、支付、回调…) | 含成功、失败、重试三条路径 |
| ④ 详细设计 | 高可用 / 高性能 / 可扩展 / 安全 / 其他 | 每节都要有措施 + 数字 + 失效时的表现 |
| ⑤ 部署方案 | 资源清单(几台、什么规格)、网络拓扑、容量水位 | 能照着买机器、开网络策略 |
| ⑥ 演进规划 | 下一版加什么、什么条件下触发重构 | 写触发条件,不写 “未来会优化” |
🔑 “不涉及”必须写 “无”,不许空着:空着会被评审默认成 “遗漏”;写 “无” 才表示 “评估过了,确实不需要”。这条能砍掉一半的来回。
容量估算:一节算出可评审的数字
设计文档里最容易被跳过、又最影响结论的一段。三段式:均摊 → 峰值 → 余量。
# 从业务量推到 TPS/QPS,三段都要写进文档
WRITE_PER_DAY = 10_000_000 # 每天新增 1000 万条
SUBSYSTEMS = 10 # 一条数据被 10 个子系统读取
PEAK_FACTOR = 3 # 峰值是均值的 3 倍
HEADROOM = 4 # 再留 4 倍余量
sec = 86400
w_avg = WRITE_PER_DAY / sec
r_avg = WRITE_PER_DAY * SUBSYSTEMS / sec
print(f"均值: 写 {w_avg:.0f}/s, 读 {r_avg:.0f}/s")
print(f"峰值 x{PEAK_FACTOR}: 写 {w_avg*PEAK_FACTOR:.0f}/s, 读 {r_avg*PEAK_FACTOR:.0f}/s")
print(f"余量 x{HEADROOM}: TPS {w_avg*PEAK_FACTOR*HEADROOM:.0f}, QPS {r_avg*PEAK_FACTOR*HEADROOM:.0f}")
本机实测输出(Python 3.14 / macOS arm64):
均值: 写 116/s, 读 1157/s
峰值 x3: 写 347/s, 读 3472/s
余量 x4: TPS 1389, QPS 13889
文档里就该写:“按 1389 TPS / 13889 QPS 做容量规划,其中读 QPS 由 10 个子系统分摊”。三段的每一段都要暴露给评审——只给最终数字,评审无法判断你到底有没有考虑峰值。
同类需要写进文档的阈值示例:
| 项 | 参考值 |
|---|---|
| 主备复制延迟告警线 | 超过 30 秒 告警(超过即读流量可能读到过期数据) |
| ZooKeeper 临时节点超时 | 默认 10 秒(决定故障摘除的检测延迟,见 48.2 服务发现) |
| 跨城同步写延迟 | ≈30ms 物理下限(决定 RPO=0 能不能做,见 36.4 两地三中心与多活) |
十条写作硬规则
| # | 规则 | 为什么 |
|---|---|---|
| 1 | 每个 NFR 后面跟数字 | “高可用” 无法验收,“4 个 9” 才能 |
| 2 | 每个 “没选” 的方案写一句否决理由 + 一个数据 | 否则评审会重新讨论一遍 |
| 3 | 图上每个方块,正文有一句职责 | 图与文字不一致是文档最常见的死法 |
| 4 | 正文写结论,理由进 ADR(58.1 ADR 实践) | 文档可读,决策可追溯 |
| 5 | 不涉及就写 “无” | 空着会被当成遗漏 |
| 6 | 部署方案要能直接下单(规格 × 台数 × 网络) | 否则上线当天才发现没资源 |
| 7 | 演进规划写 “触发条件” 而不是 “未来优化” | “未来” 永远不会来 |
| 8 | 带版本与变更记录(谁、为什么改) | 半年后没人记得为什么这么设计 |
| 9 | 术语统一,指向术语表 | 同一个东西三个名字,评审必吵 |
| 10 | 未决问题单列一节,放在最前面 | 评审会先解决争议,再听方案 |
生产落地:指名 → 可抄 → 可验 → 可退
指名:文档用 Markdown 存 Git(可 diff、可评论、可回滚),图用 Mermaid(GitHub/GitLab 原生渲染)或 PlantUML;画图的模型与规范见 80.1 C4 模型 与 80.2 架构图规范。评审流程见 58.3 架构评审。
可抄(目录骨架,直接建文件):
docs/design/<系统名>/
├── 00-选型.md # 需求介绍 / 需求分析(5W1H+8C) / 复杂度 / 备选(≥3) / 评估
├── 01-设计.md # 总体方案 / 架构总览 / 核心流程 / 详细设计 / 部署 / 演进
├── 02-容量.md # 均摊 → 峰值 → 余量,附计算脚本
├── 03-风险.md # 未决问题、已接受的风险与理由
└── adr/ # 每个关键决策一篇(格式见 ADR 实践)
文档的章节顺序不是拍出来的,它对应见 58.6 架构设计流程与三原则 里的四步流程(识别复杂度 → 3 个备选 → 环评 → 详细设计)。
可验:拿 58.3 架构评审 的十条清单逐条对,缺一条就打回。三个最硬的检查点:
| 检查 | 不合格的样子 |
|---|---|
| 备选方案 ≥ 3 个且各有一张图 | 只有一个方案,评审退化成 “要不要做” |
| NFR 全是数字 | 出现 “性能好、可用性高” |
| 部署方案能直接下单 | 只有 “部署在 K8s” 一句话 |
可退:小改动(加一个接口、换一个依赖)不套这套模板,用一页纸 RFC:背景 / 方案 / 影响面 / 回滚方式。模板是给 “不可逆、跨团队、要花钱” 的决策用的,滥用会让人把写文档当负担。
反模式
| 反模式 | 后果 |
|---|---|
| 先有方案,再补需求分析 | 评审第一个问题就崩:“你的约束是什么?” |
| 备选方案只写一个 | 评的不是 “选哪个”,而是 “要不要做”,决策质量下降 |
| 用形容词代替数字 | “高可用、低延迟” 无法验收,也无法比较 |
| 8C 只写技术维度 | 漏掉成本与合规,方案在最后一关被打回 |
| 设计文档没有部署方案 | 上线前才发现资源、网络策略、证书都没准备 |
| 图改了正文没改 | 半年后没人知道哪份是准的 |
| 文档只存邮件/IM | 找不到最新版,新人只能问人 |
| 一份文档既做选型又做设计 | 决策者被细节淹没,执行者看不到细节 |
自检
Q1 为什么选型文档和设计文档要分开写?
▸ 答案:因为读者与要回答的问题不同。选型文档面向决策者,只需回答 “为什么是它、为什么不选别的”,5–15 页就够;设计文档面向执行者,要回答 “怎么做、怎么部署、怎么回滚”,需要 20–50 页的细节。合成一份的结果是决策者嫌长、执行者嫌浅,两边都不满意。
Q2 备选方案为什么至少写 3 个?
▸ 答案:1 个方案时评审只能决定 “做不做”,没有比较就没有取舍;2 个方案常常是 “一好一坏” 的陪衬;3 个才能逼出真正的权衡(通常是一个偏保守、一个偏激进、一个折中)。这也是 58.3 架构评审 清单第 2 条的来源。
Q3 8C 里最容易被漏掉的两个维度是什么?漏了会怎样?
▸ 答案:成本与合规性。成本漏了,方案可能在预算评审时被推翻(三年 TCO 是机器 + 人力 + 迁移,不只是机器);合规漏了,可能在数据出境、等保、审计环节被卡死,返工成本远高于重新设计。
Q4 为什么 “不涉及” 必须写 “无”,不能空着?
▸ 答案:空着在评审眼里等于 “没想”。写 “无” 表示评估过并确认不需要,是结论;空着是未完成的格子。这一条能显著减少 “这里是不是漏了” 的来回确认。
Q5 容量估算的三段是什么?只写最终数字有什么问题?
▸ 答案:均摊 → 峰值 → 余量。只写最终数字(比如 “1389 TPS”),评审无法判断你有没有考虑峰值倍数与冗余系数,也无法在不同方案之间比较;三段都写出来,别人才能替换假设(峰值从 3 倍改 5 倍)自己重算。
Q6 设计文档里 “关键设计点” 和 “详细设计” 有什么区别?
▸ 答案:“关键设计点” 是3–5 条决定这套架构形状的选择(例如 “按用户分片、跨分片异步对账”),放在架构总览里,让读者一眼看到 “这套方案的骨架”;“详细设计” 是每个子系统怎么实现(表结构、接口、超时、重试),放在后面。混在一起,读者会迷失在细节里看不到骨架。
Q7 为什么文档要进 Git,而不是放在 Confluence?
▸ 答案:因为文档会过期,而过期的根因是 “更新成本高 + 与代码分离”。放进 Git 后,改代码的同一个 PR 里改文档,评审代码时顺手评审文档;还能 diff(看到改了哪一行)、能回滚、能按版本追溯。Confluence 的问题不是工具差,而是 “图与代码分属两个事实源”。