技术架构方法论 · 第 4 课
架构可视化:C4 分层画图
评审和沟通都离不开图。多数架构图失败的原因只有一个:把所有层级的信息塞进一张图,结果谁都看不懂。
知识点一:C4 的核心思想——像地图一样缩放
Simon Brown 的 C4 模型把架构图类比成地图:看国家用国家图,看街道用街道图,没有人把两者画在一张纸上。C4 定义四个缩放层级,每层一张图、回答一个问题、面向一类受众:
| 层级 | 回答什么 | 元素 | 受众 |
1. 系统上下文 Context | 这个系统在世界中的位置 | 本系统(一个框)+ 用户角色 + 外部系统 | 所有人,含非技术方 |
2. 容器 Container | 系统由哪些可独立运行的单元组成 | 应用、服务、数据库、消息总线,标注技术选型 | 研发 + 运维 |
3. 组件 Component | 某个容器内部怎么分块 | 模块/组件及职责 | 该容器的开发者 |
4. 代码 Code | 某个组件的类/函数结构 | 类图等 | 通常不画——IDE 随时能生成,画了必过期 |
易错提醒
C4 的「容器」(Container)指可独立部署运行的单元——一个后端服务、一个单页应用、一个数据库都是容器。这个命名早于 Docker 流行,与 Docker 容器无关。日常沟通中这是最高频的误解。
知识点二:一张合格的图长什么样
C4 对符号没有强制要求(不必用 UML),但每张图必须满足(c4model.com 的图规范):
- 标题写明层级与范围:"拍卖系统 — 容器图",让读者知道自己在哪一层。
- 每个框:名字 + 类型 + 技术选型:"竞价裁定服务 [服务: Java/Spring]",而不是光秃秃的"裁定"。
- 每条箭头带动词:"提交出价 [HTTPS]",而不是一根裸线——裸箭头是架构图第二大顽疾。
- 附图例:实线虚线、颜色形状各代表什么。
需要表达运行时交互顺序时补一张动态图(带编号的调用序列),表达机器分布时补一张部署图——它们是容器图的补充视角,不是替代。
知识点三:画图的顺序与止损点
- 永远先画上下文图——五分钟画完,却能暴露"外部依赖比想象多"这类致命遗漏。
- 容器图是架构评审的主图——第 3 课的场景轰炸,方案人指的就是这张图。第 2 课选的风格、量子划分,全部在这层可见。
- 组件图只给复杂容器画——简单容器(如纯 CRUD 服务)不值得画到第 3 层。
- 代码图不画。文档的敌人是过期:图越细,过期越快,止损点就设在"手工维护成本 > 阅读收益"的那一层。
随堂测验
1. C4 模型的核心思想是?
2. C4 里的「容器(Container)」指什么?
3. 实践中最常见的架构图错误是?
实战练习:拍卖系统容器图
你的任务(10 分钟,纸笔或任意画图工具,不追求美观):
- 为第 2 课的方案(服务化主体 + 事件驱动推送)画容器图:列出全部容器,每个标注类型与技术,每条连线写动词。
- 自查:买家出价 → 围观者看到新价,这条路径在你的图上能用手指走通吗?
画完再看:参考容器清单
一种合理的容器分解(技术选型仅示意):
- Web/移动前端 [SPA/App] —— 出价、围观界面
- API 网关 [网关] —— 鉴权、路由、限流
- 竞价裁定服务 [服务, 单写入点] —— 接收出价、串行裁定 → 读写竞价数据库 [RDBMS]
- 商品/拍卖管理服务 [服务] —— 上架、场次管理 → 同库或独立库
- 消息总线 [Kafka 类] —— 裁定服务发布"价格变动/成交"事件
- 推送服务 [WebSocket 集群, 可横向扩] —— 订阅事件,扇出给围观者
- 支付服务或外部支付系统——若是外部系统,应出现在上下文图并在容器图边缘标注
走通检查:前端 →[提交出价/HTTPS]→ 网关 →→ 裁定服务 →[写]→ 竞价库;裁定服务 →[发布价格事件]→ 总线 →[订阅]→ 推送服务 →[WebSocket 推送]→ 围观者前端。走不通(缺框或缺线)就是图有漏洞——这正是画图的价值:画不出来的路径,多半也没设计清楚。
课后延伸
主推资料源:c4model.com——Simon Brown 的官方站,每层都有示例图与常见错误对照,一小时能通读。画图规范速查见文档化速查(参考文档)。