共计 2499 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点
在微服务架构中,手工编写工作流代码往往会遇到许多问题:

- 状态跟踪困难:需要手动维护各个服务的执行状态,容易出错且难以调试
- 错误处理冗余:每个步骤都需要编写大量重复的错误处理代码
- 超时控制复杂:需要手动实现各种超时逻辑,代码臃肿
- 可维护性差:业务逻辑和工作流逻辑混杂在一起,难以修改
这些痛点使得工作流代码成为系统中的 ” 定时炸弹 ”,随着业务复杂度的提升,维护成本呈指数级增长。
技术对比
目前主流的工作流解决方案有以下几种:
- Cadence Skill
- 声明式 DSL 语言
- 内置状态管理
- 自动重试和超时处理
-
适用于复杂业务场景
-
AWS Step Functions
- JSON/YAML 配置
- 与 AWS 服务深度集成
- 可视化编排
-
适合简单的服务编排
-
Temporal
- 编程语言 SDK
- 强一致性保证
- 多语言支持
- 适合需要强一致性的场景
Skill 语言的优势在于其声明式语法和丰富的内置功能,可以大大减少样板代码。
核心语法
Activity 定义
activity ProcessPayment {
timeout = 30s
retryPolicy = {
initialInterval = 1s
backoffCoefficient = 2.0
maximumAttempts = 3
}
input = {
orderId: String
amount: Float
}
output = PaymentResult
}
timeout:设置 Activity 执行超时时间retryPolicy:配置重试策略,提高系统可靠性input/output:定义输入输出类型
子工作流调用
workflow ProcessOrder {
execute childWorkflow FulfillOrder with {
orderId = parentWorkflow.orderId
items = parentWorkflow.items
}
}
信号处理
signal CancelOrder {
handler = {
// 处理取消逻辑
workflow.cancel()}
}
retryPolicy 详解
retryPolicy 是确保系统可靠性的关键配置:
initialInterval:初始重试间隔backoffCoefficient:重试间隔增长系数maximumAttempts:最大重试次数nonRetryableErrorTypes:指定不重试的错误类型
合理配置重试策略可以平衡系统可靠性和响应速度。
实战示例:订单处理工作流
workflow OrderProcessing {
// 输入定义
input = {
orderId: String
items: Array<Item>
customerId: String
}
// 超时配置
executionTimeout = 1h
taskTimeout = 30s
// 信号定义
signal CancelOrder {
handler = {
// 释放预占库存
execute activity ReleaseInventory with {orderId = workflow.orderId}
// 记录取消原因
execute activity LogCancellation with {
orderId = workflow.orderId
reason = "手动取消"
}
// 终止工作流
workflow.cancel()}
}
// 主逻辑
steps {
// 1. 预占库存
reserveResult = execute activity ReserveInventory with {
orderId = workflow.orderId
items = workflow.items
} retryPolicy = {
initialInterval = 1s
backoffCoefficient = 2.0
maximumAttempts = 3
}
// 2. 处理支付(带超时)paymentTimer = timer(15m)
either {
// 支付成功分支
paymentResult = execute activity ProcessPayment with {
orderId = workflow.orderId
amount = reserveResult.totalAmount
}
} or {
// 支付超时分支
await paymentTimer
// 释放库存
execute activity ReleaseInventory with {orderId = workflow.orderId}
// 记录超时取消
execute activity LogCancellation with {
orderId = workflow.orderId
reason = "支付超时"
}
// 终止工作流
workflow.fail("支付超时")
}
// 3. 订单履约
fulfillResult = execute childWorkflow FulfillOrder with {
orderId = workflow.orderId
items = workflow.items
shippingAddress = workflow.shippingAddress
}
// 4. 发送通知
execute activity SendNotification with {
orderId = workflow.orderId
status = "completed"
customerId = workflow.customerId
}
}
}
避坑指南
- 信号丢失问题
- 问题:高负载时信号可能丢失
-
解决方案:实现信号确认机制,必要时重发信号
-
历史事件膨胀
- 问题:长期运行的工作流会产生大量历史事件
-
解决方案:配置合理的压缩策略和保留期限
-
不确定的执行
- 问题:工作流重试时产生不同的结果
- 解决方案:确保所有 Activity 都是确定性的
性能优化
对于长期运行的工作流实例,历史记录压缩至关重要:
- 启用增量压缩:只压缩新增的历史事件
- 设置合理的压缩间隔:平衡性能和资源消耗
- 限制历史记录大小:避免单个工作流占用过多存储
压缩策略示例:
workflowConfig {
historyCompression = {
enabled = true
algorithm = "zstd"
threshold = 1000 // 事件数量阈值
}
}
开放性问题
如何设计跨地域的工作流故障转移方案?考虑以下因素:
- 数据同步延迟
- 冲突解决策略
- 性能影响
- 成本考量
期待你的思考和分享!
正文完
发表至: 未分类
近两天内
