C4 模型:分层架构图绘制

FreeGuideOnline 最新 2026-07-01

什么是 C4 模型?

C4 模型是一种用于可视化软件架构的层级化方法。它将系统分解为四个抽象层次:上下文(Context)容器(Container)组件(Component)代码(Code)。每一张图都只回答一个特定的问题,避免一张图承载过多信息,让技术人员和非技术人员都能快速理解系统结构。

C4 模型的核心价值在于同一套抽象,不同角色看不同层级。你可以用统一的标准符号,从 30,000 英尺的鸟瞰图一路深入到类图细节,而不会丢失脉络。


第 1 层:系统上下文图

回答的问题

  • 我们构建的系统在整体环境中扮演什么角色?
  • 它服务哪些用户?它依赖哪些外部系统?

绘制要点

  • 中心元素:用一个大方框表示你正在构建的软件系统,通常标注名称和主要职责。
  • 人员角色:绘制人形图标,代表不同类型的用户(例如:顾客、客服、管理员)。
  • 外部系统:用灰色方框表示第三方系统、遗留系统、外部服务等。
  • 方向性关系:用带箭头的线展示数据或调用流向,并用标签简要说明交互意图(例如:“下订单”、“查询库存”)。

示例描述:一位“网上银行客户”通过“网上银行系统”查看余额,“网上银行系统”依赖“核心银行系统”获取账户数据。

这条图的受众

所有利益相关者,尤其是业务方、产品经理、架构评审委员会。它帮助大家在高层面达成“系统边界”的共识。


第 2 层:容器图

回答的问题

  • 软件系统由哪些可独立部署的技术单元组成?
  • 容器之间如何通信?技术选型是什么?

重要定义:这里的“容器”不是 Docker 容器,而是指一个可运行、存储数据或托管代码的独立单元,例如:Web 应用、移动 App、数据库、文件系统、消息队列、微服务、单页应用等。

绘制要点

  • 在系统边界内,用不同颜色或图标区分容器类型(服务、数据库、客户端等)。
  • 每个容器标注名称 + 技术选型(例如“Spring Boot 微服务”、“PostgreSQL 数据库”、“React 单页应用”)。
  • 使用带箭头的线标注通信协议和交互目的,例如:“读取/写入(JDBC)”、“发送消息(AMQP)”、“REST API(HTTPS)”。

示例描述:“网上银行系统”内部包含一个“单页应用(React)”、“API 服务(Java/Spring Boot)”和“数据库(PostgreSQL)”。SPA 通过 JSON/HTTPS 调用 API,API 通过 JDBC 访问数据库。

这条图的受众

技术团队内部,尤其是开发人员、DevOps、架构师。它能清晰展示技术栈、部署拓扑和跨容器通信方式。


第 3 层:组件图

回答的问题

  • 某个容器内部由哪些可独立工作的组件组成?
  • 这些组件之间的职责和接口如何定义?

这里的“组件”是指在一个容器进程内部、通过某种接口组织起来的一组职责封装,通常是编程语言层面的模块、包、命名空间、分层结构或一组领域服务。

绘制要点

  • 以选定的容器为边界,在其内部画出组件(用箱框表示)。
  • 每个组件标注名称和核心职责(例如:“账户管理服务”、“交易引擎”、“通知模块”)。
  • 组件间的关系通过接口名称或方法调用描述,例如:“IAccountRepository”、“INotificationSender”。

示例描述:在 API 容器中,Controller 层接收请求,调用“账户服务”组件,该组件进一步使用“账户仓储”接口访问数据库组件。同时还向“通知组件”发送异步事件。

这条图的受众

开发团队内部,常用于代码走查、模块设计评审、新成员 onboarding。它指导代码的分层与模块边界。


第 4 层:代码图

回答的问题

  • 组件内部的具体实现细节如何组织?
  • 类、接口、枚举等如何协作完成一个功能?

这一层通常可用 UML 类图、实体关系图或 IDE 自动生成的图表来表达。C4 模型并不强制要求画这一层,仅当关键复杂性需要被文档化时才绘制,避免过度维护。

绘制要点

  • 使用标准的 UML 类图符号表达类、接口、字段、方法。
  • 仅对重要的、易出错的、或架构上关键的组件进行代码级建模。
  • 优先让图表由代码反向生成,保持与实现同步。

建议:不要为每个组件都绘制代码图,而是为复杂的业务规则或遗留代码中需重构的部分保留。


符号规范与绘制工具

统一元素

C4 模型有推荐的基本符号,但鼓励团队自定义并形成图例:

  • 人员:人形图标
  • 系统:蓝色方框
  • 容器:不同颜色方框,附加技术图标
  • 组件:浅色方框,位于容器内部
  • 关系:实线(同步)、虚线(异步),带箭头与标签

推荐工具

  • Structurizr:DSL(代码即图)方式创建 C4 模型,支持版本控制和多视图渲染。
  • Draw.io / diagrams.net:提供 C4 形状库,适合快速手绘。
  • PlantUML:通过 C4 扩展语法编写文本图。
  • Mermaid:社区支持 C4 样式的渲染。
  • Lucidchart / Excalidraw:协作白板工具。

绘制 C4 模型的最佳实践

1. 从外向内,逐层深入

先画系统上下文图,确保业务边界正确;再进入容器图定义技术单元;仅在需要细节时绘制组件图。避免跳过上下文图直接进入代码细节。

2. 保持图表的自解释性

每张图必须有标题、图例、明确的边界框和描述性标签。任何人无需额外文档就能读懂。

3. 用“单页约束”控制复杂度

每张图上的元素数量建议控制在 5~15 个之间。如果一个容器内的组件超过 15 个,考虑是否引入了过多细节,或应拆分为多张聚焦不同子域的组件图。

4. 关系要紧扣“为什么”

连线上的标签必须体现实质性的交互意图,而不是简单写“调用”。例如,“验证用户身份”优于“调用 A 服务”。

5. 版本化与自动化

将 C4 图写成 Structurizr DSL 或 PlantUML 代码,纳入版本控制。与 CI 集成,确保文档与代码一同演进。

6. 避免提前深入

90% 的架构讨论只需要上下文和容器图。只有当团队对齐模块职责、评审复杂逻辑或接手遗留系统时,才需要组件图。


上手练习:为一个“电商订单系统”绘制 C4 模型

步骤 1:系统上下文图

  • 中心:电商订单系统
  • 用户:买家、商家、客服
  • 外部系统:支付网关、物流系统、邮件服务
  • 关系:买家下订单 → 系统调用支付网关收款 → 成功后通知物流系统发货 → 邮件服务发送确认

步骤 2:容器图(电商订单系统内部)

  • 买家端 Web App(React)
  • 商家端管理后台(Vue.js)
  • 订单核心服务(Go)
  • MySQL 数据库
  • Redis 缓存
  • 消息队列(Kafka)
  • 通信关系:前端通过 REST API 调用核心服务,核心服务读写数据库、缓存,并通过 Kafka 发布订单事件供物流和邮件服务消费。

步骤 3:组件图(订单核心服务容器内)

  • 订单控制器、订单服务、库存校验组件、支付适配器、订单仓储接口
  • 订单控制器接收请求 → 调用订单服务 → 组合库存校验和支付适配器 → 持久化通过订单仓储接口

完成这个练习后,你会对层级以及“何时画哪一层图”有直观感受。


常见误区

误区 正确做法
把所有层级的元素挤在一张图上 严格分层,每张图只关注一个抽象层次
在容器图中用 Docker 图标来表示容器 容器代表逻辑上的可部署单元,不是 Docker 容器
用箭头代表数据流,不加任何文字说明 必须添加标签明确交互目的和协议
每张图都深入代码级别 仅在必要的局部区域绘制代码图,避免维护噩梦
只有架构师才画 C4 整个团队可以共同维护同一套 .dsl 或 .puml 文件,形成活文档

C4 模型的核心是用一致的抽象语言,在不同细节级别上沟通架构意图。从今天开始,为你的系统尝试绘制第一张系统上下文图吧。