Skip to content

03 · 读懂与画好架构图:C4 模型

上一章你学会了把系统想清楚。这一章解决下一个问题:怎么把脑子里那个系统,画成别人一眼就懂的图。 架构师一大半的工作不是设计,而是沟通——而图,是沟通的主力工具。


为什么架构师必须会画图

先纠正一个误解:画架构图,不是为了好看,也不是为了交差,而是为了一件最朴素的事——让别人和你看到的是同一个系统。

想象一下:你脑子里那个系统是清晰的,数据怎么流、谁依赖谁、边界在哪,你门儿清。但它锁在你脑子里。 你的产品经理不知道,后端同事各有各的理解,前端以为是另一回事。于是十个人,脑子里装着十个略有不同的系统——这是几乎所有项目混乱的根源。

架构图的作用,就是把你脑中那个系统倒出来,摆到桌面上,让所有人对着同一张图说话。它的价值,在于对齐:

   没有图:                          有图:

   产品脑中    后端脑中               所有人
   的系统      的系统                 看着同一张
     │           │                     图说话
     ▼           ▼                       │
   我以为      我以为                    ▼
       ↘       ↙                    我们说的
         冲突、返工                    是同一个东西

一句话:架构师的产出,不只是想清楚,还得让团队都清楚。 想清楚了却讲不明白,在团队协作里,几乎等于没想清楚。会画图,是把个人的判断力,变成团队的共识——这是架构师的核心工作,不是附加技能。

而且,画图本身就是一种思考。 当你试图把脑中的系统画下来,常会发现「咦,这两个东西到底谁调谁?」「这里的边界其实我没想清楚」——图会逼你把含糊的地方想明白。 画不出来,往往就是还没想清楚的信号。


先看看烂图长什么样

在学怎么画好之前,先认认坏味道。你一定见过这种图:一堆五颜六色的方块,密密麻麻的箭头横七竖八,看半天不知道它想说什么。烂图比没有图更糟,因为它制造一种我们沟通过了的错觉,实际上每个人理解的还是不一样。

烂图通常犯这几个毛病:

┌─────────────────────────────────────────────────────────────┐
│  烂图四宗罪                                                    │
├─────────────────────────────────────────────────────────────┤
│  ① 没有边界    所有框平铺在一起,分不清哪些在一个进程/         │
│                一台机器/一个信任域里。                         │
│                                                              │
│  ② 箭头没方向  线就是线,不知道是 A 调 B 还是 B 调 A,         │
│                也不知道线上跑的是什么:数据?调用?事件?      │
│                                                              │
│  ③ 抽象层次混乱 一张图里,整个支付系统和某个工具函数          │
│                画在同一层。大小不一的概念混在一起,看的人       │
│                不知道该用什么颗粒度理解。                       │
│                                                              │
│  ④ 框太多      四十个方块挤在一页,信息量爆炸,                │
│                看的人直接放弃。                               │
└─────────────────────────────────────────────────────────────┘

第三条抽象层次混乱最隐蔽,也最致命,值得多说一句。它就像一张地图上,既画了整个中国,又画了你家小区的某栋楼——这两个东西的尺度差了十万八千里,放在一起,看的人完全不知道该站在多高的视角去理解。

好图的反面,正是治好这四宗罪:有清晰的边界、箭头标明方向和含义、一张图只用一个抽象层次、框的数量受控。 那么,有没有一套现成的方法,能帮我们系统地做到这些?有,它叫 C4 模型


C4 模型:像用地图软件一样,分层级看系统

C4 模型的核心思想,和你用地图软件的体验一模一样。

你查路线时,不会用同一个缩放级别看完所有东西:先看中国地图知道城市在哪,放大到市区图看主干道,再放大到街道图看具体怎么走。每一层只显示那一层该有的信息,多一分则乱,少一分则空。

C4 把架构图也分成这样四个缩放级别,从最宏观到最微观:

   缩放级别        C4 层次              画的是              给谁看

   🌍 中国地图  →  ① Context 上下文   整个系统 + 周边     所有人
                                       用户、外部系统     含非技术

                        ▼ 放大,钻进我们的系统内部
   🏙️ 市区图    →  ② Container 容器   系统由哪几个         技术团队
                                       可独立运行的       架构、运维、
                                        大块组成          技术负责人

                        ▼ 放大,钻进某一个容器内部
   🛣️ 街道图    →  ③ Component 组件   一个容器内部         开发这块的
                                       由哪些模块组成        工程师

                        ▼ 放大,钻进某一个组件内部
   🏠 楼栋图    →  ④ Code 代码        类、函数怎么组织      基本不画,
                                                          交给 IDE

C4 这个名字,就来自这四层的英文首字母:Context、Container、Component、Code。

它最大的贡献,是直接根治了烂图的第三宗罪——抽象层次混乱。 因为它强制你:一张图,只待在一个缩放级别上。 你要么画整个系统的全貌,要么钻进某一块看它内部,绝不在一张图里混着画。

下面逐层看。重点掌握前两层,也就是 Context 和 Container,因为它们是日常用得最多、也最能体现架构判断的两层。

第①层:Context:系统上下文 —— 给所有人看

这是缩放到最远的一层。在这张图里,你的整个系统就是中间一个框。对,整个系统就一个框,内部细节一概不画。周围画的是:谁在用它,比如用户、各种角色;以及它要和哪些外部系统打交道,比如支付网关、邮件服务、第三方登录。

它回答的是最高层的问题:这个系统是干嘛的?它和外面的世界怎么交互?

   Context 图示例:一个在线书店

        ┌──────────┐                      ┌──────────────┐
        │  顾客    │                      │  出版社系统    │
        │ 用户     │                      │ 外部,供货     │
        └────┬─────┘                      └──────▲───────┘
             │ 浏览、下单                          │ 同步库存
             ▼                                    │
        ┌─────────────────────────────────────────┴────┐
        │                                               │
        │            在 线 书 店 系 统                    │
        │          我们要做的东西,内部先不展开             │
        │                                               │
        └──────┬──────────────────────────┬─────────────┘
               │ 发起支付                   │ 发送订单邮件
               ▼                            ▼
        ┌──────────────┐            ┌──────────────┐
        │  支付网关     │            │  邮件服务     │
        │ 外部         │            │ 外部         │
        └──────────────┘            └──────────────┘

给谁看:所有人,包括产品经理、老板、客服——任何不写代码但需要理解系统在生态里扮演什么角色的人。 这张图的妙处是,它一个技术名词都没有,非技术的人也能看懂,所以特别适合用来对齐我们到底在做什么。

第②层:Container:容器 —— 给技术团队看

把上一层中间那个整个系统的框放大、钻进去,你看到的就是 Container 层。

这里的 Container,也就是容器,不是指 Docker 那种容器。别被名字骗了。在 C4 里,它指的是一个可以独立运行、独立部署的大块——比如一个前端应用、一个后端服务、一个数据库、一个缓存。判断标准很简单:它是不是一个能单独启动、单独部署的进程或存储? 是,它就是一个 Container。

这一层回答:我们的系统,内部由哪几个能独立运行的大块组成?它们之间怎么通信?数据存在哪?

   Container 图示例:把上面那个在线书店系统放大

   ┌──────────┐
   │  顾客    │
   └────┬─────┘
        │ HTTPS

   ┌─────────────────────────────────────────────────────────┐
   │  在线书店系统:虚线 = 系统边界,框内都是我们的           ┊
   ┊                                                          ┊
   ┊   ┌──────────────┐      调用 API      ┌───────────────┐  ┊
   ┊   │  Web 前端     │ ─────────────────▶ │  后端服务      │  ┊
   ┊   │ 浏览器应用    │ ◀───────────────── │ 处理业务逻辑   │  ┊
   ┊   └──────────────┘      返回 JSON      └───┬───────┬───┘  ┊
   ┊                                            │       │      ┊
   ┊                              读写订单/商品  │       │ 缓存热门商品
   ┊                                            ▼       ▼      ┊
   ┊                                  ┌──────────┐  ┌────────┐ ┊
   ┊                                  │ 数据库    │  │ 缓存    │ ┊
   ┊                                  └──────────┘  └────────┘ ┊
   └──────────────────────────────────────────────────────────┘

给谁看:技术团队——架构师、技术负责人、运维。 因为这一层直接对应部署和运维:每个 Container 通常就是一个要部署、要监控、可能要扩容的单元。这也是架构判断最密集的一层——拆成几个服务、数据库怎么分、要不要加缓存,这些上一章讲的取舍,大多体现在这张图上。

💡 你或许注意到了:本仓库每个模板的架构全景图,基本就画在 Container 这个层次。 比如 AI 对话产品模板 的第 4 节那张图,里面的接入层、编排层、推理服务、会话存储、向量检索,每一个都是一个可独立运行的大块——这就是一张典型的 Container 图。学会读 Container 图,你就能读懂本仓库几乎所有的全景图。

第③层:Component:组件 —— 给开发这块的人看

再放大,钻进某一个 Container,比如上面的后端服务,看它内部由哪些模块构成——比如订单模块、商品模块、用户认证模块,以及它们怎么协作。

   Component 图示例:把后端服务这一个容器放大

   ┌──────────────────────────────────────────────────┐
   │  后端服务:放大看它内部                              │
   │                                                    │
   │   ┌────────────┐      ┌────────────┐               │
   │   │ 订单模块    │ ───▶ │ 库存模块    │               │
   │   └─────┬──────┘      └─────┬──────┘               │
   │         │                   │                       │
   │         ▼                   ▼                       │
   │   ┌────────────┐      ┌────────────┐               │
   │   │ 支付对接    │      │ 数据访问层  │ ──▶ 到数据库   │
   │   └────────────┘      └────────────┘               │
   └────────────────────────────────────────────────────┘

给谁看:要开发这个 Container 的工程师。 它帮一个团队内部就这块代码怎么分模块、谁负责谁达成一致。注意:只有当某个 Container 复杂到值得拆解时,才需要画它的 Component 图——简单的就别画了。

第④层:Code:代码 —— 通常不画

最后一层,是具体到类、函数怎么组织。

说实话,这一层基本不用手画。 因为代码本身、以及 IDE 自动生成的关系图,就是最准确、最实时的 Code 图——你手画一张,代码一改它就过时了。所以 C4 模型自己都说:Code 层按需偶尔画一下即可,绝大多数时候跳过。

这本身就是个朴素的工程智慧:别去手工维护一份代码一改就过时的文档。 你的精力,该花在 Context 和 Container 这种相对稳定、又最需要沟通的层次上。


画图的基本元素:就三样

C4 看着花哨,但你手里真正的画笔其实只有三样东西。把这三样的含义钉死,你的图就不会乱。

   ┌─────────┐
   │  框     │   = 一个有职责的东西。
   └─────────┘     它得能回答:你是干嘛的。一个系统、一个服务、
                   一个模块都行,但同一张图里,所有框的尺度要一致。

       ───▶       = 箭头 = 一段关系。
                   关键:① 一定有方向,谁主动找谁;
                        ② 一定标含义,线上跑的是调用?数据?事件?
                   没方向、没含义的线,是烂图的头号来源。

   ┌ ─ ─ ─ ─ ┐
   ┊ 边界    ┊   = 一条分界线。
   └ ─ ─ ─ ─ ┘     圈住属于一起的东西。它可能是:
                   • 部署边界:这些跑在同一台机器/集群里
                   • 信任边界:框内是我们可信的,框外的输入都不可信
                   • 系统边界:哪些是我们的,哪些是外部的

这三样里,新人最常忽略边界,而它恰恰最能体现架构思维。 一条边界,常常同时意味着部署在哪和信任到哪——比如上一章那个 AI 模板里反复强调的任何重新进入系统的外部数据都不可信,在图上,就是一条把我们的系统和外部输入分开的信任边界。边界画在哪,往往就是安全和部署决策的所在。


几条能立刻让你的图变好的原则

把这五条记下来,贴在显示器边上。它们直接对治前面说的四宗罪:

  1. 一张图,只用一个抽象层次。 这是 C4 的灵魂,也是最重要的一条。别在画整个系统的图里,突然塞进一个具体函数。要么都是大块,要么都是模块,不许混。 这一条专治第③宗罪。

  2. 箭头一定标方向和含义。 每根线都要能回答两个问题:谁找谁?为了什么?在线旁写上调用 API、读写数据、发送事件之类的几个字。一根没标注的线,就是一个没想清楚的依赖。 这一条专治第②宗罪。

  3. 控制框的数量,控制在 7±2。 人一眼能抓住的东西大约就 7 个上下。一张图超过 9 个框,就该考虑:是不是该往上抽一层、或者拆成两张图了。 信息要分层喂,不是一次性砸过去。这一条专治第④宗罪。

  4. 先画 Context,再往下钻。 永远从最宏观的那张图开始,确认系统和外界的关系对齐了,钻进去画 Container。自顶向下,别一上来就陷进某个组件的细节里——那样你很容易只见树木不见森林。

  5. 图是给人看的,不是给机器看的。 时刻问自己:我的读者是谁?他需要这个信息吗?给老板看的 Context 图里别出现技术黑话;给工程师看的 Container 图别为了简洁省掉关键的数据流。永远为你的读者画图。


ASCII 画图实用技巧

本仓库统一用纯文本 ASCII 画图——因为它在任何地方都能显示、能直接放进 Markdown 和代码注释、还能用文本 diff 看出改了什么,朴素但极其实用。 这里给你几个上手的小技巧:

   ① 框:用方块字符围起来
      ┌─────────┐     横线 ─   竖线 │   四个角 ┌ ┐ └ ┘
      │  服务 A  │     交叉 ┼   丁字 ┬ ┴ ├ ┤
      └─────────┘

   ② 箭头:标清方向
      ──▶  ◀──  ▲  ▼        单向依赖
      ◀──▶  或上下各一条      双向交互,如请求/响应

   ③ 边界:用虚线和实线区分
      ┌─────────┐           实线框:一个具体的东西
      └─────────┘
      ┌ ─ ─ ─ ─ ┐           虚线框:一条边界,系统/信任/部署
      ┊         ┊
      └ ─ ─ ─ ─ ┘

   ④ 在箭头旁边加文字,说明这根线在干嘛。最重要!
      A ───调用 API───▶ B
      A ◀──返回结果──── B

几个小提醒:

  • 先在草稿纸或白板上画,想清楚布局再誊成 ASCII。 ASCII 改起来不如随手画的方便,所以先想后画更重要。
  • 善用对齐和留白。 把同一层的框横向对齐、纵向拉开,图会清爽很多。挤在一起的 ASCII 图,可读性会断崖式下降。
  • 不必追求像素级完美。 ASCII 图的目标是讲清结构和关系,不是当艺术品。能让人看懂数据怎么流、谁依赖谁,就成功了。

你不用从头死记这些字符。最好的学法,是直接去本仓库的模板里抄——看 AI 对话产品模板 的全景图怎么用框和箭头,照着模仿,几次就熟了。


动手练一练

光看不练,学不会画图。给你一个具体的练习,强烈建议真的动手做一遍:

练习:

  1. 打开 ../templates/,挑任意一个你感兴趣的系统,比如电商、社交信息流、实时通讯。
  2. 先别看它的全景图! 只读它开头的一句话定位和核心需求,然后自己动手,画一张它的 Context 图:中间一个框是这个系统,周围是用户和它要打交道的外部系统。用纸笔或 ASCII 都行。
  3. 画的时候,刻意应用本章的原则:框是不是只用了一个抽象层次?箭头有没有标方向和含义?有没有圈出系统边界?
  4. 画完,再去对照模板里的架构全景图。那是一张 Container 图。

对照时,重点体会两件事:

  • 你的 Context 图,也就是最远的视角,和它的 Container 图,也就是钻进去一层,是不是正好差了一个缩放级别? ——感受 C4 分层的威力:你画的整个系统一个框,放大进去,就是模板里那一堆相互协作的大块。
  • 模板全景图里,有没有你没想到的外部系统或内部大块? 它为什么需要那个东西?——这一问,又回到了第 02 章的为什么画图不只是画图,它逼着你重新理解这个系统的每一个决策。

📌 真实案例:C4 模型不是我们发明的

本章用的 C4 模型,来自 Simon Brown 提出的同名方法论,如今是业界画架构图的事实标准之一。

  • 📎 官方:c4model.com —— 有更完整的四层定义、记号约定和大量真实示例。
  • 本仓库 26 个模板的全景图,基本都画在 C4 的 Container 层——学会读它,就能读懂仓库里几乎所有系统。

🎯 随堂检验

🤔你要给产品、后端、运维各讲一遍系统,但每人只需要看清自己那一层。最符合 C4 灵魂的做法是?
  • A画一张超大图,从用户一直画到每个类和方法,一次讲全
  • B按 Context → Container → Component 分层出图,每张图只待在一个抽象级别
  • C只画 Container 层,因为技术团队才需要看图

本章小结

  • 画图的本质是对齐,让团队所有人看到同一个系统。架构师一大半的工作是沟通,图是沟通的主力工具;想清楚却讲不明白,约等于没想清楚。而且画图本身会逼你把含糊处想透。
  • 烂图四宗罪:没边界、箭头没方向、抽象层次混乱、框太多。 其中抽象层次混乱最致命——就像一张地图既画整个国家又画你家楼栋。
  • C4 模型像地图软件的缩放级别,分四层:Context,整个系统+周边,给所有人;Container,可独立运行的大块,给技术团队;Component,容器内的模块,给开发者;Code,基本不画。它的灵魂是:一张图只待在一个缩放级别。
  • 本仓库的全景图,基本都是 Container 层的图。 学会读它,就能读懂仓库里几乎所有系统。
  • 画图的画笔只有三样:框、箭头、边界。 框代表有职责的东西,箭头代表标方向和含义的关系,边界代表部署/信任/系统的分界。新人最易忽略边界,而它最能体现架构思维。
  • 五条原则:一张图一个抽象层次、箭头标方向和含义、控制框数 7±2、先 Context 再下钻、永远为你的读者画图。

到这里,第一段建立思维就走完了:你知道了为什么架构判断越来越值钱,见 01;有了一套想清楚系统的框架,见 02;也学会了把想法画出来、讲明白,见 03。

但你可能会问:每次都从零开始想吗?前人遇到的那些经典难题,有没有现成的招式可以套用?

有。接下来的第二段掌握工具箱,就是来给你发牌的——架构师手里那些反复被验证过的模式,每一个都是对某一类问题的标准答案。

👉 继续阅读:04 · 十大核心架构模式

💬 评论