3、系统架构文档:架构图绘制规范

系统架构文档,说白了就是给整个项目画一张「地图」。

我见过太多团队,代码写得飞起,但问起系统长什么样,每个人脑子里都有一幅不同的画。结果呢?联调时才发现接口对不上,部署时发现模块依赖乱成一锅粥。

所以,架构图不是画给领导看的摆设。它是团队沟通的通用语言。今天我就把我在多个项目中沉淀下来的绘制规范,掰开揉碎了讲给你听。

3.1 上下文图(Context Diagram)

上下文图是架构文档的第一张图。它的作用只有一个:划定系统边界

你想想看,一个系统再复杂,它也是跟外部世界打交道的。谁在用你的系统?你的系统依赖了哪些外部服务?这些就是上下文图要回答的问题。

核心要素:

  • 系统本身:用一个矩形框表示,框内写系统名称
  • 外部用户:用小人图标或角色名表示,比如「终端用户」、「管理员」
  • 外部系统:用矩形框表示,比如「支付网关」、「短信平台」
  • 交互关系:用带箭头的连线表示,箭头上标注数据流或协议

我个人习惯,上下文图只用一张图,不要超过 10 个外部实体。如果超过,说明你的系统边界没划清楚。

我的经验:

有一次我在项目中画上下文图,发现系统居然直接依赖了三个不同的数据库。后来一查,有两个是历史遗留的,根本不需要。你看,一张图就能暴露问题。

3.2 容器图(Container Diagram)

上下文图之后,我们放大一步,看系统内部。容器图展示的是系统由哪些「容器」组成。

这里的「容器」不是 Docker 容器,而是指:Web 应用、移动 App、数据库、消息队列、微服务等独立部署的单元。

容器类型 图例样式 示例
Web 应用 矩形 + 浏览器图标 前端 SPA、管理后台
后端服务 矩形 + 齿轮图标 用户服务、订单服务
数据库 圆柱体 MySQL、Redis
消息队列 矩形 + 队列图标 Kafka、RabbitMQ

画容器图时,我建议你注意三点:

  • 每个容器都要标注技术栈,比如「Java Spring Boot」、「Node.js Express」
  • 容器之间的通信协议要写清楚,是 HTTP/REST 还是 gRPC,还是异步消息
  • 不要画得太细,容器图只到「部署单元」级别,再细就是组件图的事了

避坑指南:

我曾经见过有人把容器图画成了部署架构图,连 IP 地址和端口号都标上去了。没必要。容器图关注的是逻辑关系,不是物理部署。

3.3 组件图(Component Diagram)

组件图是架构图的最后一层。它把一个容器拆开,展示内部有哪些组件,以及组件之间的调用关系。

举个例子,「用户服务」这个容器内部,可能有这些组件:

  • Controller:接收 HTTP 请求
  • Service:处理业务逻辑
  • Repository:访问数据库
  • Client:调用外部服务

画组件图时,我有个习惯:每个组件只写它的核心职责,不要写方法名。比如「用户注册」、「密码校验」这种,而不是「registerUser()」、「checkPassword()」。

组件图的关键信息:

  • 组件名称
  • 组件职责(一句话)
  • 组件之间的依赖关系(箭头方向从调用方指向被调用方)
  • 组件使用的关键技术(如 Spring Data JPA、Redis Client)

3.4 接口定义表

光有图还不够。图是给人看的,接口定义是给机器和代码看的。

接口定义表要包含以下字段:

字段 说明 示例
接口名称 简短描述接口功能 用户注册
请求方法 GET / POST / PUT / DELETE POST
请求路径 完整的 URL 路径 /api/v1/users/register
请求参数 参数名、类型、是否必填 username(string, 必填), password(string, 必填)
响应格式 成功和失败的响应结构 { "code": 0, "data": { "userId": 123 } }
错误码 可能返回的错误码及含义 1001: 用户名已存在

我的建议:

接口定义表最好跟代码中的 API 文档自动同步。我习惯用 Swagger/OpenAPI 规范,然后从代码生成文档。这样接口改了,文档不会忘更新。

3.5 技术选型说明

技术选型说明,是架构文档里最容易被人忽略,但最体现功底的部分。

很多人写技术选型,就列个表格:用了什么框架、什么数据库。完了。这不行。

你要写清楚:为什么选这个,不选那个

举个例子:

  • 数据库选了 PostgreSQL 而不是 MySQL,为什么?因为我们需要 JSONB 数据类型和地理空间查询
  • 消息队列选了 RabbitMQ 而不是 Kafka,为什么?因为我们的业务场景是任务分发,不是日志流处理,RabbitMQ 的 ACK 机制更适合
  • 前端框架选了 React 而不是 Vue,为什么?因为团队里大部分人熟悉 React,而且项目需要大量的状态管理

技术选型说明的模板:

## 技术选型:消息队列

### 选型结果
RabbitMQ 3.12.x

### 备选方案
- Apache Kafka 3.5.x
- Redis Stream

### 选型理由
1. 业务场景:任务分发,需要可靠的消息确认机制
2. 团队经验:团队有 RabbitMQ 的生产运维经验
3. 运维成本:已有 RabbitMQ 集群,无需额外部署

### 风险与应对
- 风险:RabbitMQ 吞吐量不如 Kafka
- 应对:当前业务峰值 2000 TPS,RabbitMQ 可支撑 1 万 TPS,预留 5 倍余量

避坑指南:

我曾经见过一个项目,技术选型写的是「因为 Redis 快,所以用 Redis 做消息队列」。结果业务量上来后,消息丢失、数据不一致,改都改不动。技术选型不是比谁快,而是比谁更适合。

嗯,到这里,系统架构文档的核心内容就讲完了。记住一句话:图是骨架,表是血肉,选型说明是灵魂。三者缺一不可。