共计 2590 个字符,预计需要花费 7 分钟才能阅读完成。
1. 背景介绍
Cadence 是一个分布式工作流编排引擎,而技能 (Skill) 功能是其核心特性之一。简单来说,技能功能允许你将复杂的业务逻辑封装成可重用的组件,就像乐高积木一样可以灵活拼装。

使用技能功能的三大优势:
- 代码复用:避免重复造轮子,相同的业务逻辑只需开发一次
- 降低复杂度:将大工作流拆解为小技能,便于维护和调试
- 提高可靠性:内置重试机制和超时处理,增强系统容错能力
2. 核心概念
2.1 技能功能架构
graph TD
A[工作流] -->| 调用 | B(技能)
B --> C{执行逻辑}
C -->| 成功 | D[返回结果]
C -->| 失败 | E[自动重试]
2.2 关键组件
- 技能接口(Skill Interface):定义技能的输入输出规范
- 技能实现(Skill Implementation):包含实际业务逻辑
- 执行上下文(Context):提供运行时环境信息
- 重试策略(Retry Policy):控制失败时的自动重试行为
3. 实现步骤
3.1 环境准备
- 安装 Cadence 服务端和 CLI 工具
- 配置 Go/Python 开发环境
- 初始化 Cadence 客户端连接
3.2 技能定义
以 Python 为例,定义一个简单的邮件发送技能:
from cadence.worker import Worker
from cadence.activity import activity_method
# 定义技能接口
@activity_method(task_list="EmailTaskList", schedule_to_close_timeout_seconds=60)
class EmailSkill:
@staticmethod
async def send(subject: str, recipient: str, body: str) -> bool:
"""
:param subject: 邮件主题
:param recipient: 收件人邮箱
:param body: 邮件正文
:return: 发送是否成功
"""
# 实际发送逻辑实现
return True
3.3 工作流集成
from cadence.workflow import workflow_method, Workflow
@workflow_method(execution_start_to_close_timeout_seconds=300,
task_list="OrderProcessing")
class OrderWorkflow:
def process_order(self, order_id: str):
# 调用邮件技能
email_result = yield EmailSkill.send(
subject="订单确认",
recipient="customer@example.com",
body=f"您的订单 {order_id} 已受理"
)
if not email_result:
# 错误处理逻辑
pass
4. 完整代码示例
以下是 Go 语言的完整实现示例:
package main
import (
"context"
"go.uber.org/cadence/activity"
"go.uber.org/cadence/workflow"
)
// 定义技能接口
const EmailSkillName = "emailSkill"
type EmailSkill struct {
Subject string
Recipient string
Body string
}
// 技能实现
func EmailActivity(ctx context.Context, skill EmailSkill) (bool, error) {logger := activity.GetLogger(ctx)
logger.Info("Sending email", skill)
// 实际发送逻辑
return true, nil
}
// 工作流集成
func OrderWorkflow(ctx workflow.Context, orderID string) error {
ao := workflow.ActivityOptions{
ScheduleToStartTimeout: time.Minute,
StartToCloseTimeout: time.Minute,
RetryPolicy: &cadence.RetryPolicy{
InitialInterval: time.Second,
BackoffCoefficient: 2.0,
MaximumInterval: time.Minute,
},
}
ctx = workflow.WithActivityOptions(ctx, ao)
// 调用技能
var success bool
err := workflow.ExecuteActivity(ctx, EmailActivity, EmailSkill{
Subject: "订单确认",
Recipient: "customer@example.com",
Body: fmt.Sprintf("您的订单 %s 已受理", orderID),
}).Get(ctx, &success)
if err != nil {return err}
return nil
}
5. 最佳实践
5.1 性能优化
- 批量处理:合并多个小技能调用为单个批量操作
- 异步执行 :非关键路径使用
fire-and-forget模式 - 缓存结果:对重复计算使用 Memoization 技术
5.2 错误处理
- 分级重试:根据错误类型配置不同重试策略
- 熔断机制:对第三方服务调用添加熔断保护
- 死信队列:将无法处理的错误路由到专门队列
6. 常见问题
Q1: 技能执行超时
现象 :日志显示ScheduleToCloseTimeout 错误
解决:
1. 检查网络延迟
2. 适当增加超时时间
3. 拆分长时间运行业务为多个小技能
Q2: 工作流卡死
现象 :工作流状态长期处于Running 但无进展
解决:
1. 使用 cadence workflow reset 命令重置
2. 检查技能是否在等待永远不会发生的事件
Q3: 技能结果不一致
现象:相同输入得到不同输出
解决:
1. 确保技能实现是幂等的
2. 检查是否有外部状态被修改
7. 实践建议
- 从简单技能开始,比如日志记录或数据转换
- 使用模拟对象 (Mock) 测试技能边界条件
- 逐步构建技能库,形成自己的工具集
- 参与开源社区,学习他人优秀实现
通过将复杂业务流程分解为可组合的技能,你可以像搭积木一样快速构建可靠的工作流系统。记住,好的技能设计应该像 Unix 哲学倡导的那样:只做一件事,并做到极致。
正文完
发表至: 未分类
近两天内
