类图描绘「一个类怎么和别的类互动」,组件图描绘「文件 / 模块怎么组装」,部署图描绘「运行时节点怎么连」。三层一起用是描述完整架构的标准做法。
三层架构图
| 层级 |
描绘什么 |
读者 |
PlantUML 关键字 |
| 类图 |
类之间的字段、方法、继承关系 |
开发 |
class / abstract / interface |
| 组件图 |
文件 / 模块 / 服务 / 库 之间的依赖 |
架构师 / Tech Lead |
component / package |
| 部署图 |
节点(服务器 / 容器 / 进程)的网络位置和协议 |
架构师 / 运维 |
node / cloud / database |
组件图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| @startuml title 单体应用组件图
package "Web App" { [Auth Controller] as Auth [Article Controller] as Article [Comment Controller] as Comment }
package "Service Layer" { [User Service] as UserSvc [Article Service] as ArticleSvc [Notification Service] as NotiSvc }
package "Data Layer" { database "PostgreSQL" as DB [Redis Cache] as Cache }
Auth --> UserSvc Article --> ArticleSvc Comment --> CommentService UserSvc --> DB ArticleSvc --> DB ArticleSvc --> Cache NotiSvc --> ArticleSvc
@enduml
|
要点:
[名字] 表示组件,渲染成带接口圆圈的矩形
package "X" { ... } 表示包,渲染成带标签的大圆角矩形
database "X" as 别名 表示数据存储,渲染成圆柱体
--> 是依赖关系
加接口和实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @startuml title 组件接口
interface "IDataStore" as IDataStore interface "INotifier" as INotifier
package "实现类" { [PostgresStore] as PgStore [EmailNotifier] as EmailN [SmsNotifier] as SmsN }
package "业务类" { [OrderService] as OrderSvc }
PgStore ..|> IDataStore EmailN ..|> INotifier SmsN ..|> INotifier OrderSvc --> IDataStore : 使用 OrderSvc --> INotifier : 调用
@enduml
|
..|> 表示实现接口(实线 + 三角箭头)。
嵌套组件
组件图支持嵌套:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @startuml package "前端项目" { package "src/components" { [LoginForm.tsx] [ArticleList.tsx] } package "src/api" { [userApi.ts] [articleApi.ts] } }
[LoginForm.tsx] --> [userApi.ts] [ArticleList.tsx] --> [articleApi.ts] @enduml
|
这样画可以让读者一眼看清代码组织。
部署图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| @startuml title 微服务生产部署
node "Client Browser" { [React SPA] }
node "CDN" { [静态资源] }
node "API Gateway (Nginx)" { [nginx] }
node "Kubernetes Cluster" { node "Pod: user-svc" { [User Service] } node "Pod: article-svc" { [Article Service] } node "Pod: payment-svc" { [Payment Service] } }
node "AWS RDS" { database "PostgreSQL" }
node "AWS ElastiCache" { database "Redis" }
[React SPA] --> [静态资源] : 加载 [React SPA] --> [nginx] : API
[nginx] --> [User Service] : HTTP [nginx] --> [Article Service] : HTTP [nginx] --> [Payment Service] : HTTP
[User Service] --> [PostgreSQL] [Article Service] --> [PostgreSQL] [Article Service] --> [Redis] [Payment Service] --> [PostgreSQL]
@enduml
|
node "X" { ... } 表示一个部署节点(服务器 / 容器 / 集群)。可以任意嵌套,表达「某 Pod 部署在 K8s 集群上运行的某个 Container 里」这种层级。
节点类型关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @startuml node browser [ <&desktop> 浏览器 ] node server [ <&server> 应用服务器 ] node lb [ <&gear> 负载均衡 ] database "PostgreSQL" { } cloud "Cloud Service" { }
browser --> server server --> database server --> cloud @enduml
|
<&name> 关键字插入 Font Awesome 风格图标。
PlantUML 支持的节点关键字:
| 关键字 |
含义 |
渲染 |
node |
通用节点 |
矩形 |
cloud |
云服务 |
云形状 |
database |
数据库 |
圆柱 |
frame |
浏览器 / iframe |
3D 矩形 |
component |
组件 |
接口圆圈矩形 |
package |
包 |
大圆角矩形 |
<<device>> 等 |
自定义 stereotype |
自定义 |
关联线
1 2 3 4 5 6
| A --> B : HTTP/JSON A ..> B : async message A ==> B : sync remote call A --|> B : extends A ..|> B : implements A .. B : dashed dependency
|
不同箭头类型:
| 箭头 |
含义 |
视觉 |
A --> B |
关联 |
实线 + 空箭头 |
A ..> B |
依赖 |
虚线 + 空箭头 |
A ==> B |
关联(强) |
实线 + 双箭头 |
A --|> B |
泛化 |
实线 + 空心三角 |
A ..|> B |
实现 |
虚线 + 空心三角 |
跨子图:架构图 + 部署图并列
把组件图和部署图并列画:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| @startuml left to right direction
frame "组件视图" { [User Service] [Article Service] [PostgresDB] [User Service] --> [PostgresDB] [Article Service] --> [PostgresDB] }
frame "部署视图" { node "k8s cluster" { node "pod 1" { [User Service] } node "pod 2" { [Article Service] } } node "AWS RDS" { [PostgresDB] } }
@enduml
|
实战:电商系统
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| @startuml title 电商系统 - 组件视图
package "前端" { [Web SPA] [Mobile App] }
package "网关" { [API Gateway] }
package "微服务" { [User Service] [Product Service] [Order Service] [Payment Service] [Inventory Service] [Notification Service] }
package "消息总线" { queue "Kafka" as K }
package "数据存储" { database "User DB" as UDB database "Product DB" as PDB database "Order DB" as ODB database "Cache" as Cache }
[Web SPA] --> [API Gateway] [Mobile App] --> [API Gateway]
[API Gateway] --> [User Service] [API Gateway] --> [Product Service] [API Gateway] --> [Order Service]
[Order Service] --> [Payment Service] [Order Service] --> [Inventory Service]
[Order Service] --> K [Payment Service] --> K K --> [Notification Service]
[User Service] --> UDB [Product Service] --> PDB [Order Service] --> ODB [Order Service] --> Cache [Inventory Service] --> PDB
@enduml
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| @startuml title 电商系统 - 部署视图
node "Client" { [Web SPA] [Mobile App] }
cloud "AWS Cloud" { node "Region: us-east-1" { node "ALB" { [API Gateway] } node "EKS Cluster" { node "namespace: svc" { node "pod: user" { [User Service] } node "pod: product" { [Product Service] } node "pod: order (3 replicas)" as PodOrder { [Order Service] } node "pod: payment" { [Payment Service] } node "pod: inventory" { [Inventory Service] } } node "MSK" { queue "Kafka" as K } } node "RDS" { database "PostgreSQL Multi-AZ" as RDS } node "ElastiCache" { database "Redis Cluster" as Cache } } }
[Web SPA] --> [API Gateway] : HTTPS [Mobile App] --> [API Gateway] : HTTPS [API Gateway] --> [User Service] [API Gateway] --> [Product Service] [API Gateway] --> [Order Service]
PodOrder --> RDS PodOrder --> Cache [Inventory Service] --> RDS @enduml
|
组件图说「代码组织」,部署图说「运行时位置」。
评审 checklist
踩坑清单
- 组件太多:一张组件图 5-15 个组件。多了就分组或拆图。
- 组件图混入运行时信息:组件图表达「编译时依赖」,部署图表达「运行时位置」。一张图一个关注点。
- 节点嵌套层级太深:3 层以上部署图会看不清。建议外层用 namespace / cluster,内层只 2 层。
- 箭头方向不规范:
A --> B 应该表示 A 依赖 B / A 调用 B / A 给 B 发消息。从语义上要统一。
- C4 不混用:用 C4 的项目就别自己再画组件图,统一表达方式。
与时序图的关系
组件图 + 部署图 + 时序图 = 完整架构描述:
| 图类型 |
描绘 |
一句话类比 |
| 组件图 |
代码模块组织 |
「我家有几间房间」 |
| 部署图 |
运行时节点位置 |
「这几间房在城市哪个位置」 |
| 时序图 |
调用顺序 |
「客人从哪扇门进来,经过哪几间房,走哪条路」 |
画完组件图、部署图,再画几张关键时序图,文档就完备了。
一句话总结
组件图表达「怎么写」,部署图表达「怎么跑」。PlantUML 两类图都覆盖得很完整,能让架构文档和代码同步更新而不腐烂。