PlantUML 完整项目案例:一个微服务从 0 到 1

puml.online

把之前所有 PlantUML 知识用到极致 —— 一份完整的电商订单微服务系统,从需求到上线的全套图表。

项目背景

假设我们要设计一个电商订单微服务

  • 订单生命周期:待付款 → 已付款 → 已发货 → 已签收 → 已完成 / 已退款
  • 微服务拆分:订单 / 支付 / 库存 / 用户 / 推荐
  • 数据存储:PostgreSQL + Redis + Kafka
  • 部署:Kubernetes

下面 8 张图覆盖这个项目的关键阶段。

图 1:用例图 —— 业务范围

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
@startuml
left to right direction
skinparam actorStyle awesome
title 电商订单系统 - 业务用例

actor "游客" as Guest
actor "会员" as Member
actor "管理员" as Admin
Member <<Human>>

rectangle "电商订单系统" {
usecase "浏览商品" as UC1
usecase "搜索" as UC2
usecase "加购物车" as UC3
usecase "下单" as UC4
usecase "支付" as UC5
usecase "查看订单" as UC6
usecase "申请退款" as UC7
usecase "管理商品" as UC8
usecase "查看报表" as UC9
}

Guest --> UC1
Guest --> UC2
Member --> UC1
Member --> UC3
Member --> UC4
Member --> UC5
Member --> UC6
Member --> UC7
Admin --> UC8
Admin --> UC9

UC4 ..> UC5 : <<include>>
UC4 ..> UC3 : <<include>>
UC7 ..> UC5 : <<extend>>
UC5 ..> "会员认证" : <<include>>
@enduml

评审:让 PM 检查是否覆盖全部业务场景。

图 2:C4 上下文 —— 系统与外部依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@startuml
!include /plantuml/c4/C4_Context.puml
LAYOUT_TOP_DOWN()

Person(buyer, "顾客", "Web / Mobile")
Person(admin, "运营", "后台")

System(orderSys, "订单系统", "订单生命周期")

System_Ext(paySvc, "支付网关", "支付宝 / 微信")
System_Ext(logistics, "物流系统", "仓库配送")
System_Ext(cdm, "CDN", "静态文件")
System_Ext(sso, "SSO", "统一登录")

Rel(buyer, orderSys, "下单", "HTTPS")
Rel(admin, orderSys, "管理", "HTTPS")
Rel(buyer, cdm, "加载资源")
Rel(orderSys, paySvc, "扣款")
Rel(orderSys, logistics, "下发履约")
Rel(orderSys, sso, "Token 验证")
@enduml

评审:让架构组确认系统边界和外部依赖。

图 3:组件图 —— 内部模块

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
@startuml
title 订单服务 - 组件视图

package "frontend" {
[Web SPA]
[Mobile App]
}

package "edge" {
[API Gateway]
}

package "order-svc" {
[OrderController]
[OrderDomain]
[OrderEventPublisher]
[OrderRepo]
}

package "data" {
database "Order DB" as ODB
database "Cache" as Cache
queue "Kafka" as K
}

[Web SPA] --> [API Gateway]
[Mobile App] --> [API Gateway]

[API Gateway] --> [OrderController]
[OrderController] --> [OrderDomain]
[OrderDomain] --> [OrderRepo]
[OrderRepo] --> ODB
[OrderRepo] --> Cache
[OrderDomain] --> [OrderEventPublisher]
[OrderEventPublisher] --> K
@enduml

评审:让 Tech Lead 检查服务边界划分。

图 4:类图 —— 领域模型

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
59
60
61
62
63
64
65
66
67
68
69
@startuml
skinparam classAttributeIconSize 0

class Order {
-id: String <<UK>>
-customerId: Long
-status: OrderStatus
-items: List<OrderItem>
-total: Money
+place()
+pay()
+ship()
+complete()
+refund()
}

class OrderItem {
-productId: Long
-quantity: int
-unitPrice: Money
}

class Money {
-amount: BigDecimal
-currency: String
}

class Customer {
-id: Long
-name: String
-email: String
}

class Product {
-id: Long
-sku: String
-name: String
-price: Money
}

enum OrderStatus {
PENDING
PAID
SHIPPED
DELIVERED
CANCELLED
REFUNDED
}

abstract class AggregateRoot {
+id: Long
{abstract} +validate()
}

interface Auditable {
+createdAt: Instant
+updatedAt: Instant
}

AggregateRoot <|-- Order
Auditable ..|> Order
Auditable ..|> Customer

Order "1" *-- "1..*" OrderItem
Order "1" --> "1" Customer
OrderItem "1" --> "1" Product
Order "1" --> "1" OrderStatus
OrderItem "1" --> "1" Money
@enduml

评审:让架构组确认聚合根、关联、枚举。

图 5:状态图 —— 订单生命周期

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
@startuml
title 订单状态机

[*] --> 待付款 : 提交订单

待付款 --> 已付款 : 支付成功 / 扣减库存
待付款 --> 已取消 : 用户主动取消
待付款 --> 已超时 : 24h [定时任务]

已付款 --> 待发货 : 系统确认
已付款 --> 已退款 : 申请退款 [审批通过]

待发货 --> 已发货 : 仓库出库 / 队列发送
待发货 --> 已退款 : 申请退款 [审批通过]

已发货 --> 已签收 : 用户签收 / 触发积分
已发货 --> 售后中 : 申请售后

已签收 --> 已完成 : 7 天 [自动]
已签收 --> 售后中 : 申请售后

售后中 --> 售后完成 : 仅退款 / 仅换货
售后中 --> 已退款 : 同意退款

已退款 --> [*]
已取消 --> [*]
已超时 --> [*]
已完成 --> [*]
售后完成 --> [*]

note right of 已签收 : 订单自动关闭触发 7 天后
note left of 售后中 : 这里开始是退款流程
@enduml

评审:让业务方对每个状态含义验收。

图 6:时序图 —— 下单完整流程

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
@startuml
title 下单完整时序

actor 顾客
participant "前端" as FE
participant "API 网关" as GW
participant "订单服务" as Os
participant "库存服务" as Is
participant "支付服务" as Ps
participant "Kafka" as K
participant "通知服务" as Ns

顾客 -> FE: 点击「提交订单」
FE -> GW: POST /orders
GW -> Os: createOrder(payload)
Os -> Is: lockStock(items)

alt 库存足够
Is --> Os: ok

Os -> Os: 计算总价
Os -> GW: 200 + orderId
GW --> FE: 200 + orderId
FE --> 顾客: 跳转支付

Os -> Ps: pay(orderId)
Ps -> Ps: 调支付网关
alt 支付成功
Ps --> Os: ok
Os --> K: publish OrderPaid
K --> Ns: 收到 OrderPaid
Ns --> 顾客: 邮件通知
else 支付失败
Ps --> Os: fail
Os -> Is: unlockStock
Os --> K: publish OrderFailed
end
else 库存不足
Is --> Os: error
Os --> GW: 409 + 「缺货」
GW --> FE: 409 + 「缺货」
FE --> 顾客: 提示库存不足
end

@enduml

评审:让技术评审者看跨服务调用的合理性。

图 7:部署图 —— K8s 拓扑

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
59
60
61
62
63
64
65
66
@startuml
title 订单系统 - 生产部署

node "客户端" {
[Web SPA]
[Mobile App]
}

cloud "AWS Cloud" {
node "Region us-east-1" {
node "ALB" {
[API Gateway]
}

node "EKS Cluster" {
node "namespace: order" {
node "Deployment" {
node "Pod 1" {
[Order Service]
}
node "Pod 2" {
[Order Service]
}
node "Pod 3" {
[Order Service]
}
}
node "Deployment" {
node "Pod 1" {
[Payment Service]
}
}
node "Deployment" {
node "Pod 1" {
[Inventory Service]
}
}
}

node "MSK" {
queue "Kafka" as K
}
}

node "RDS" {
database "PostgreSQL Multi-AZ" as PDB
}

node "ElastiCache" {
database "Redis Cluster" as Cache
}
}
}

[Web SPA] -[#2F4858]-> [API Gateway] : HTTPS
[Mobile App] -[#A31F34]-> [API Gateway] : HTTPS

[API Gateway] -[#2F4858]-> [Order Service] : HTTP
[Order Service] -[#2F4858]-> [Payment Service] : HTTP
[Order Service] -[#2F4858]-> [Inventory Service] : HTTP

[Order Service] -[#2F4858]-> PDB : SQL
[Order Service] -[#2F4858]-> Cache : Cache
[Order Service] -[#20A464]-> K : 发布事件

@enduml

评审:让 SRE 确认 HA / 副本 / 边界。

图 8:PR 描述里的时序图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
## PR: 订单退款流程

### 修改

增加订单退款状态。退款成功后从「售后中」转为「已退款」。

### 修改前

下单退款不规范——直接置为「已取消」,丢失退款流程。

### 修改后

![refund flow](docs/sequence/refund-after.puml)

PR Author: 给订单退款加了显式状态机。
Reviewer: 看状态图 / 时序图确认符合业务侧的需求。

图 9:CI 自动渲染

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
# .github/workflows/plantuml-render.yml
name: PlantUML render
on:
push:
paths: ['docs/**/*.puml']
branches: [main]
pull_request:
paths: ['docs/**/*.puml']

jobs:
render:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with: { java-version: '21', distribution: temurin }
- run: |
sudo apt-get update && sudo apt-get install -y fonts-noto-cjk
curl -L -o plantuml.jar \
https://github.com/plantuml/plantuml/releases/latest/download/plantuml.jar
find docs -name '*.puml' | while read f; do
java -jar plantuml.jar -tsvg -failfast2 -nometadata "$f"
done
- name: Verify SVGs up-to-date
run: |
git diff --quiet docs/ || (
echo "::warning::Some SVGs out of sync with their .puml sources"
git diff --name-only docs/ | head
exit 1
)
- name: Auto-commit regenerated SVGs
if: failure()
run: |
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
git add docs/
git commit -m "render: regenerate SVGs [skip ci]"
git push

8 张图 + 1 个 CI = 完整项目档案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
docs/
architecture/
c4-context.puml → public/architecture/c4-context.svg
components/
order-svc.puml → public/components/order-svc.svg
sequence/
place-order.puml → public/sequence/place-order.svg
refund-after.puml → public/sequence/refund-after.svg
state/
order-lifecycle.puml → public/state/order-lifecycle.svg
deployment/
production.puml → public/deployment/production.svg
class/
domain.puml → public/class/domain.svg
usecase/
business.puml → public/usecase/business.svg

评审 checklist

让每张图各司其职

评审人 关注点
用例图 PM / 业务 业务覆盖
C4 上下文 架构师 系统边界
组件图 Tech Lead 模块拆分
类图 架构师 领域模型
状态图 业务 + 开发 业务规则
时序图 开发 调用关系
部署图 SRE HA / 副本
PR 描述 评审者 改动理解

PR 中分别用哪张

  • 新功能 → 用例图 + 时序图 + 类图更新
  • 修复 bug → 状态图(说明 bug 在哪个状态)+ 时序图(说明修复在哪条路径)
  • 基础设施变更 → 部署图更新
  • 架构重构 → C4 + 组件图重新画

完整 case 实际用

把这一份实例项目塞给新人,让他们感受到「从需求到代码到上线」每一步都有图,省去读 100 页 wiki 的时间。

反模式

1. 一张大图包罗万象

1
2
3
@startuml
note: from business to deployment, everything in one SVG
@enduml

一张图承担 8 个视角,渲染慢 + 评审更慢。

2. 时序图只画成功路径

1
2
3
4
@startuml
顾客 -> 服务: 调用
服务 --> 顾客: OK
@enduml

不画失败路径,debug 时就要靠文字描述。

3. 部署图只有一张

部署图每次变动都更新,CI 自动 commit。一张图就是永远新鲜的当前状态。

一句话总结

PlantUML 整套实践不是「一张图」,是「多张图按阶段、读者、审查点拆分」。本文的 8 张图是一个完整模板,可以直接套用到任何微服务项目。

  • 标题: PlantUML 完整项目案例:一个微服务从 0 到 1
  • 作者: puml.online
  • 创建于 : 2026-07-29 16:25:00
  • 更新于 : 2026-08-14 21:34:29
  • 链接: https://puml.online/blog/plantuml-real-project-case/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。