Serverless 事件驱动架构:Lambda / Step Functions / EventBridge / Saga

puml.online

Serverless 不只是「不用管服务器」——核心是事件驱动 + 异步编排。这篇是 AWS Lambda + Step Functions + EventBridge + SQS/SNS 的实战组合,以及 Saga 补偿、事件溯源、冷启动优化、PlantUML 时序图画异步链路。

Serverless 全景(AWS)

1
2
3
4
5
6
7
8
9
事件源                          计算                        存储/下游
─────── ───── ─────────
API Gateway → Lambda → DynamoDB
S3 事件 → Lambda → S3 (处理后的文件)
EventBridge 定时器 → Step Functions → ECS / Fargate
DynamoDB Streams → Lambda → Kinesis
SNS 通知 → Lambda → SES (邮件)
SQS 队列 → Lambda → Step Functions
ALB → Lambda → RDS Proxy → RDS

Lambda 函数架构

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 "Lambda Function Internal Architecture"

actor "Caller" as C
participant "Lambda Runtime" as Runtime
participant "Handler Function" as Handler
participant "Init Code" as Init
database "DynamoDB" as DB
participant "External API" as API
participant "CloudWatch Logs" as Logs

C -> Runtime : ① invoke {payload}

alt Cold Start
Runtime -> Init : ② 初始化 (VPC ENI, SDK clients, ORM)
Init -> DB : ③ 创建连接池
Init -> Logs : ④ 记录 init 耗时
end

Runtime -> Handler : ⑤ handler(event, context)
Handler -> Handler : ⑥ 业务逻辑
Handler -> DB : ⑦ query / write
Handler -> API : ⑧ HTTP call
Handler -> Logs : ⑨ 结构化日志

Handler --> Runtime : ⑩ 返回结果 / throw error
Runtime --> C : ⑪ response (success / fail)

note right of Handler
Warm Start:
Init 不再跑,直接 handler
Cold Start: 100ms - 5s
Warm Start: 1ms - 100ms
end note

@enduml

冷启动优化:

  • Provisioned Concurrency——预热实例,无冷启动
  • 减少部署包大小——Lambda Layer 分离依赖
  • SnapStart (Java)——冷启动 < 200ms
  • 避免 VPC——VPC ENI 慢,没必要时 Lambda 不放 VPC
  • 连接复用——RDS Proxy / DynamoDB SDK 都支持连接池

API Gateway + Lambda 同步调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@startuml
title "API Gateway + Lambda Sync"

actor "Client" as C
participant "API Gateway" as GW
participant "Lambda" as Fn
database "DynamoDB" as DB

C -> GW : ① GET /api/users/123
GW -> GW : ② 验证 JWT / API Key
GW -> Fn : ③ invoke (同步)
Fn -> DB : ④ GetItem
DB --> Fn : ⑤ user record
Fn --> GW : ⑥ 200 {user: {...}}
GW --> C : ⑦ 200

note right of Fn
超时限制:
- Lambda: 15 分钟
- API Gateway: 29 秒
- ALB: 相同
end note

@enduml

API Gateway 超时比 Lambda 短——长任务用异步。

SQS + Lambda 异步解耦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@startuml
title "SQS + Lambda Async Decoupling"

actor "Client" as C
participant "API Gateway" as GW
participant "Lambda (Producer)" as Producer
queue "SQS Queue" as Q
participant "Lambda (Consumer)" as Consumer
database "DynamoDB" as DB

C -> GW : ① POST /api/orders {items: [...]}
GW -> Producer : ② invoke
Producer -> Producer : ③ 验证请求
Producer -> Q : ④ SendMessage {order_id, payload}
Producer --> GW : ⑤ 202 Accepted {order_id}
GW --> C : ⑥ 202 Accepted

note over Q : SQS 持久化,Lambda 失败自动 retry

Q -> Consumer : ⑦ poll (batch)
Consumer -> DB : ⑧ PutItem order
Consumer -> Q : ⑨ DeleteMessage (成功后)

@enduml

优势:

  • 削峰——SQS 缓冲突发请求
  • 重试——Lambda 失败,SQS 自动 retry (可见性超时)
  • DLQ——多次失败进 Dead Letter Queue
  • 解耦——Producer / Consumer 独立部署

EventBridge 总线模式

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
@startuml
title "EventBridge Event Bus Pattern"

participant "Order Service" as Order
participant "EventBridge Bus" as EB
participant "Payment Lambda" as Pay
participant "Inventory Lambda" as Inv
participant "Email Lambda" as Email
participant "Analytics Lambda" as Analytics

Order -> EB : ① PutEvents {OrderPlaced, order_id, items}

EB -> EB : ② 路由匹配 rule

par 并行触发
EB -> Pay : ③ OrderPlaced → 处理支付
EB -> Inv : ④ OrderPlaced → 预扣库存
EB -> Email : ⑤ OrderPlaced → 发送确认邮件
EB -> Analytics : ⑥ OrderPlaced → 记录分析事件
end

note right of EB
EventBridge 规则:
- source = "com.orders"
- detail-type = "OrderPlaced"
- 可加 filter (如 region)
- target 多 targets 并行
end note

@enduml

EventBridge 优势:

  • 解耦——发送方不知道谁订阅
  • 多目标并行——一个事件触发多个下游
  • 跨账号——事件可以跨 AWS account 路由
  • SaaS 集成——直接对接 Datadog / Zendesk / PagerDuty

Step Functions 编排长流程

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
@startuml
title "Step Functions State Machine"

state "OrderReceived" as S1
state "ValidateOrder" as S2
state "ChargePayment" as S3
state "ReserveInventory" as S4
state "ShipOrder" as S5
state "NotifyCustomer" as S6
state "OrderCompleted" as S7
state "OrderFailed" as SF
state "RefundPayment" as SR

S1 --> S2
S2 --> S3 : valid
S2 --> SF : invalid
S3 --> S4 : payment_ok
S3 --> SR : payment_failed
S4 --> S5 : inventory_ok
S4 --> SR : inventory_failed\n→ refund first
S5 --> S6 : shipping_ok
S6 --> S7

SR --> SF
SF --> [*]
S7 --> [*]

@enduml

Step Functions 状态机文件(ASL):

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
{
"Comment": "Order processing workflow",
"StartAt": "ValidateOrder",
"States": {
"ValidateOrder": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:validateOrder",
"Next": "ChargePayment",
"Catch": [{
"ErrorEquals": ["ValidationError"],
"Next": "OrderFailed"
}]
},
"ChargePayment": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:chargePayment",
"Next": "ReserveInventory",
"Retry": [{
"ErrorEquals": ["ThrottlingException"],
"IntervalSeconds": 2,
"MaxAttempts": 3
}],
"Catch": [{
"ErrorEquals": ["PaymentFailed"],
"Next": "RefundPayment"
}]
},
"ReserveInventory": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:reserveInventory",
"Next": "ShipOrder"
},
"ShipOrder": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:shipOrder",
"Next": "NotifyCustomer"
},
"NotifyCustomer": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:notifyCustomer",
"End": true
},
"RefundPayment": {
"Type": "Task",
"Resource": "arn:aws:lambda:...:refundPayment",
"Next": "OrderFailed"
},
"OrderFailed": {
"Type": "Fail",
"Cause": "Order processing failed"
}
}
}

优势:

  • 可视化——状态机图直接看流程
  • 自动 retry——内置 retry 策略
  • 错误处理——Catch block 显式处理失败
  • 长任务——最长 1 年,支持 wait state

Saga 模式(分布式事务补偿)

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
@startuml
title "Saga Pattern - Distributed Transaction with Compensation"

actor "User" as U
participant "Order Service" as Order
participant "Payment Service" as Payment
participant "Inventory Service" as Inventory
participant "Shipping Service" as Shipping

U -> Order : ① 下单
Order -> Order : ② 创建订单 (status=pending)
Order -> Payment : ③ 扣款
Payment --> Order : ④ 成功 / 失败

alt Payment 成功
Order -> Inventory : ⑤ 预扣库存
Inventory --> Order : ⑥ 成功 / 失败

alt Inventory 成功
Order -> Shipping : ⑦ 创建运单
Shipping --> Order : ⑧ 成功 / 失败

alt Shipping 成功
Order -> Order : ⑨ status=confirmed
else Shipping 失败
Order -> Inventory : ⑩ 补偿:释放库存
Order -> Payment : ⑪ 补偿:退款
Order -> Order : ⑫ status=cancelled
end

else Inventory 失败
Order -> Payment : ⑬ 补偿:退款
Order -> Order : ⑭ status=cancelled
end

else Payment 失败
Order -> Order : ⑮ status=cancelled
end

@enduml

Saga 两种实现:

  • 编排式(Orchestration)——中央协调器(Step Functions)调用每个 service
  • 编舞式(Choreography)——每个 service 监听事件,自己决定下一步

事件溯源(Event Sourcing)

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
@startuml
title "Event Sourcing Pattern"

actor "User" as U
participant "Command Handler" as Cmd
participant "Aggregate" as Agg
queue "Event Store\n(DynamoDB Stream / Kinesis)" as Store
participant "Projection" as Proj
database "Read Model\n(DynamoDB)" as Read
participant "Query Handler" as Q

U -> Cmd : ① PlaceOrder {items}
Cmd -> Agg : ② load aggregate
Agg -> Agg : ③ 业务规则校验
Agg -> Store : ④ append OrderPlaced {order_id, ...}
Store -> Proj : ⑤ stream event
Proj -> Read : ⑥ update read model

U -> Q : ⑦ GET /orders/{id}
Q -> Read : ⑧ query
Read --> Q : ⑨ order info

note right of Store
Event Store 特点:
- 不可变(append-only)
- 按时间顺序
- 可重放(replay)
end note

@enduml

事件溯源 vs 传统 CRUD:

传统 CRUD 事件溯源
存储 当前状态 状态变更事件序列
历史 丢失 完整
审计 内置
调试 看当前 + log 重放事件

SNS Fan-Out + SQS 队列扇出

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 "SNS Fan-Out to Multiple SQS"

participant "Producer Service" as P
participant "SNS Topic" as SNS
queue "SQS - Email Queue" as Q1
queue "SQS - SMS Queue" as Q2
queue "SQS - Analytics Queue" as Q3
participant "Lambda Email" as Email
participant "Lambda SMS" as SMS
participant "Lambda Analytics" as Analytics

P -> SNS : ① Publish {message}
SNS -> Q1 : ② Fan-out
SNS -> Q2 : ③ Fan-out
SNS -> Q3 : ④ Fan-out

Q1 -> Email : ⑤ poll
Q2 -> SMS : ⑥ poll
Q3 -> Analytics : ⑦ poll

note right of SNS
SNS Fan-Out:
- 一对多推送
- 每个订阅独立消费
- 不影响其他订阅
end note

@enduml

Fan-Out 优势:消息发给多个下游,各自独立消费,不影响

DynamoDB Streams 触发 Lambda

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 "DynamoDB Streams + Lambda"

database "DynamoDB Table" as Table
participant "DynamoDB Stream" as Stream
participant "Lambda (CDC)" as Lambda
participant "OpenSearch" as ES
participant "S3 (Data Lake)" as S3

Table -> Stream : ① INSERT/UPDATE/DELETE 自动捕获
Stream -> Lambda : ② trigger (new image, old image)
Lambda -> ES : ③ 索引更新
Lambda -> S3 : ④ 写入数据湖 Parquet
Lambda -> Stream : ⑤ checkpoint (已处理)

note right of Stream
DynamoDB Streams:
- 24 小时 retention
- 按 partition key 顺序
- 触发器可配置 batch size
end note

@enduml

典型用法:

  • 实时索引到 OpenSearch——搜索
  • 数据湖 ETL——分析
  • 跨区域复制——DR
  • 缓存失效——同步 Redis

冷启动优化实战

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
@startuml
title "Lambda Cold Start Optimization"

start

:选择运行时(Runtime);
note right: Node.js/Python 比 Java 快

:部署包大小控制;
note right: <50MB 最佳
:用 Lambda Layer 分离依赖

:VPC 配置;
note right: 没必要时不要 VPC

:Provisioned Concurrency;
note right: 预热 N 个实例
:消除冷启动

:SnapStart (Java);
note right: 启动 < 200ms

:连接复用;
note right: RDS Proxy / SDK connection pool

:代码优化;
note right: 模块顶层初始化 client
:handler 内只放业务逻辑

:监控;
note right: CloudWatch 指标 Init Duration

stop

@enduml

冷启动基准(典型场景):

  • Node.js: 100-300ms
  • Python: 200-500ms
  • Java: 1-3s (无 SnapStart); 200ms (有 SnapStart)
  • .NET: 1-2s

Lambda 调用链可视化(用 PlantUML)

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
@startuml
title "Lambda Distributed Trace (X-Ray)"

actor "User" as U
participant "API Gateway" as GW
participant "Lambda: OrderAPI" as L1
queue "SQS" as Q
participant "Lambda: OrderProcessor" as L2
participant "Lambda: PaymentProcessor" as L3
database "DynamoDB" as DB

U -> GW : ① GET /api/orders
GW -> L1 : ② invoke
L1 -> DB : ③ Query
L1 -> Q : ④ SendMessage (异步)
L1 --> GW : ⑤ 200

Q -> L2 : ⑥ 异步触发
L2 -> L3 : ⑦ 调用另一 Lambda
L3 -> DB : ⑧ UpdateItem
L3 --> L2 : ⑨ success
L2 -> DB : ⑩ UpdateItem order.status

note over GW
X-Ray Service Map:
API Gateway → OrderAPI → SQS → OrderProcessor → PaymentProcessor → DynamoDB

每个 segment 显示延迟占比
找最慢的环节
end note

@enduml

X-Ray / CloudWatch ServiceLens 自动画这种调用链,PlantUML 用于文档化设计

实战踩坑

  • Lambda 单实例并发限制——账户默认 1000,爆量时 throttling申请提配额或用 SQS 削峰
  • Lambda 超时——同步调用 API Gateway 29s,异步最长 15min。长任务用 Step Functions
  • Step Functions 状态机太大——超过 200 个 state 编译慢。拆成多个 state machine,用 nested execution
  • EventBridge rule 配额——每个 bus 默认 300 rules。跨 bus 路由或合并 rule
  • DLQ 没配置——失败消息无限重试。每个 SQS/EventBridge target 配 DLQ
  • DynamoDB Stream 24h 后丢——超长 lag 数据丢失。用 Kinesis Data Stream 替代
  • 冷启动突袭——白天冷启动延迟大,Provisioned Concurrency 预热
  • VPC Lambda 网络费用——NAT Gateway 数据传出按 GB 收,很贵VPC Endpoint 走内网,或者 Lambda 不放 VPC
  • 异步调用无响应——Lambda 异步 invoke 不返回结果。用 Destination 配置成功/失败后处理

决策树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
任务是什么?
├─ HTTP 同步 API(< 30s) → API Gateway + Lambda
├─ HTTP 同步长任务 → API Gateway → SQS → Lambda(异步)
├─ 异步处理(图片/视频) → S3 event → Lambda
├─ 定时任务 → EventBridge 定时 → Lambda
├─ 多步骤工作流 → Step Functions
├─ 数据库变更捕获 → DynamoDB Stream → Lambda
├─ 一对多推送 → SNS Fan-Out
└─ 跨服务事件总线 → EventBridge

需要事务一致性?
├─ 不需要 → EventBridge + Lambda(最终一致)
├─ 强一致本地事务 → RDS + Lambda
├─ 跨服务事务 → Saga 模式(补偿)
└─ 复杂状态机 → Step Functions + Saga

最小 Serverless 起步:API Gateway + Lambda + DynamoDB。加异步:加 SQS。加工作流:加 Step Functions。加解耦:加 EventBridge。

记住:Serverless 不是万能——长任务用 Fargate/EC2,本地开发用 docker-compose。Lambda 是 glue 不是 application server。

  • 标题: Serverless 事件驱动架构:Lambda / Step Functions / EventBridge / Saga
  • 作者: puml.online
  • 创建于 : 2026-07-30 17:50:00
  • 更新于 : 2026-08-14 21:34:29
  • 链接: https://puml.online/blog/plantuml-serverless-event-driven/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。