中文 | English
go-fsm 是一个分布式状态机开发框架,核心是自动化的状态流转,能帮助开发者更简单地开发出需要完成分布式事务的应用。
本项目安全可靠
,是我在一些金融业务上的成功实践。
go.mod 引入
require (
github.com/HEUDavid/go-fsm latest
)
一个状态处理器示例
func newHandler(task *Task[*MyData]) error {
log.Printf("[FSM] State: %s, Task.Data: %s", task.State, _pretty(task.GetData()))
// It may be necessary to perform some checks.
// It may be necessary to pre-record the request to the database to ensure idempotency.
// For example, generating some request IDs.
// ...
task.Data.Comment = "Modified by newHandler" // Update Data
task.State = Pay.GetName() // Switch to next state
return nil
}
一个最简单的支付流程: New -> Pay -> End,其状态机定义如下
(注: 完整Demo项目链接)
var (
New = GenState("New", false, newHandler)
Pay = GenState("Pay", false, payHandler)
End = State[*MyData]{Name: "End", IsFinal: true, Handler: nil}
)
var (
New2Pay = GenTransition(New, Pay)
Pay2End = GenTransition(Pay, End)
End2End = GenTransition(End, End)
)
var PayFSM = func() FSM[*MyData] {
fsm := GenFSM[*MyData]("PayFSM")
fsm.RegisterState(New, Pay, End)
fsm.RegisterTransition(New2Pay, Pay2End, End2End)
return fsm
}()
通过代码可生成其状态机图(左图),另一个稍微复杂的示例(右图)
_ = PayFSM.Draw("pay.svg")
- Adapter: 接受外部调用(对服务接口协议没有要求),核心数据读写,接口满足幂等性
- Worker: 基于MQ消息驱动,状态处理器,Worker调用安全可重入
- 描述状态机:
- 简便描述状态机的节点和边(状态跃迁)、绘制状态机
- 状态处理器: 开发者只需实现具体业务逻辑,框架完成消息分发、调度等
- 中间件支持:
- 数据存储: MySQL,支持事务,可方便地嵌入到其他业务中
- 消息中间件: RabbitMQ、Amazon Simple Queue Service
- 其他类型的中间件可按interface自行拓展
- 泛型支持:
对Golang的泛型支持地特别好!!!
开发业务代码特别简单,结构清晰!重写逻辑非常简单!
- 数据更新流水: 待支持
- 高并发性: 支持水平扩展
- 可靠性强: 满足幂等性、一致性、原子性、可重入原则
- 灵活扩展: 可按interface灵活拓展,自由重写,任意逻辑,任意组件
- 金融支付系统
- 证券清算结算业务
- 复杂工作流程管理
- 需要状态管理的高并发系统
- 接口的幂等性
- Create: request_id唯一键保证其幂等性
- Update: request_id唯一键保证其幂等性,以及version控制(乐观锁,在DB层面所以性能很好)
- 状态跃迁的可靠性
- 接口与Worker扭转状态,先取当前状态,判断动作是否在预先定义的状态转移表中
- 更新基于版本号
- 状态处理器的可重入
- 开发者调用其他外部接口时注意幂等性,则满足系统可重入(调用安全)
- 消息会丢吗(使用框架的MQ组件)?
- 当状态处理器返回error时,不会执行ACK(执行NACK如果NACK不为nil),可以配置MQ服务端使重新入队
- RMQ集群是可靠的,但万一消息丢了也无妨。消息是无状态的,可使用脚本工具运维补发,或实现监控逻辑补发( 一个实践是对状态进行停留检测)
- AWS Amazon Simple Queue Service,更可靠,利用删除消息和消息可见性机制实现了ACK与NACK逻辑
- 自恢复
- 对于一些可以恢复的临时故障(例如网络中断、数据库服务重启,RMQ服务重启等)能够自动恢复,无需人工干预
- 大概是秒级中断
- 如何设计一个FSM应用