状态机

1 项目概述

1.1 背景介绍及目标

1.1.1 背景

状态机工作流 -- State Machine(强调的是状态的改变)

State Machine 工作流则一般用于 方向不明确的事情当中,一件事完成 (state activity) 面临着很多不同的选择,并且,这个选择要依赖于人的决定(事件驱动)。 State machine 往往是可逆的。一个状态 (State Activity) 有可能要被多次的执行。 比如在线购物便可以看成一个 state machine workflow. 工作流的进行往往有赖于外部事件(比如人)的推动。 再有,如看电视,可以开电视,可以关电视,可以随便转台,也可以专注看某个节目,状态与状态间并没有一个必然的顺序关系。 如此,我们便可以使用 state machine workflow.

1.1.2 场景

  • 机器的生命周期管理(外部机器,初始化中,备机,线上运行中,故障,维修,下架)

  • 实例的生命周期管理

  • 审批流

实例生命周期

例子:
> 实例的部署状态
+-------------------add-----------------------+  +-recover-+
|                                             V  V         |
none—>allocated—>deployed—>installed—>ready->running---->dead---->removed
                                                |        ^ |          ^
                                                +--kill--+ +--delete--+

备注:这里的 dead 状态指与上下游实例已解除关系,非停止实例

(1) 触发 event(unit delete)
(2) 状态机 State1(dead) 转变为 State2(removed)
(3) 触发相关 action(下发 task 将实例删除)

> 实例的运行状态(比如 redis)
状态有 pfail,fail 等

> 容器的运行状态
* created
* running
* stopped
* paused
* deleted

机器生命周期管理

机器管理

1.2 名词说明

有限状态机,(英语:Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。

事件-> 状态 -> 动作

1.3 Roadmap

2 需求分析

2.1 功能需求

2.2.1 有限状态机一般都有以下特点:

  • 1 可以用状态来描述事物,并且任一时刻,事物总是处于一种状态

  • 2 事物拥有的状态总数是有限的

  • 3 通过触发事物的某些行为,可以导致事物从一种状态过渡到另一种状态

  • 4 事物状态变化是有规则的,A 状态可以变换到 B,B 可以变换到 C,A 却不一定能变换到 C

  • 5 同一种行为,可以将事物从多种状态变成同种状态,但是不能从同种状态变成多种状态。

2.2.2 这里需要注意的两个问题:

1、避免把某个“程序动作”当作是一种“状态”来处理

2、状态划分时漏掉一些状态,导致跳转逻辑不完整。

状态表格传送门

2.2 非功能需求

2.3 调研

2.3.1 状态机

2.3.1.1 transitions

https://github.com/pytransitions/transitions

2.3.1.2 python-statemachine

https://github.com/fgmacedo/python-statemachine

2.3.1.3 OpenStack automaton

https://github.com/openstack/automaton

创建一个简单的状态机

输出

变更一个状态机状态

输出

初始化 m.initialize() 完后,这个状态图挺有意思的

  • @ 用于标记当前状态

  • [^] 用于标记初始状态,使用 m.default_start_state = 'down' 声明

  • [$] 用于标记终止状态,使用 m.add_state("lies down", terminal=True) 声明

2.3.2 可视化

  • transitions 自带的 transitions-gui

    • 基于 tornado WebSocket 模块实现了"服务端直接向客户端推送数据而不需要客户端进行请求"

    • 基于 cytoscape.js cytoscape 是一个网络图的可视化工具,大量的生物分子 / 基因领域的公司用它来做可视化分析。由于它的通用性,慢慢的也被其他领域的人用来做网络的可视化和分析。

  • 基于 pygraphviz

    • https://github.com/pytransitions/transitions/issues/258

3 总体设计

3.1 系统架构

一般来说会有个简单的架构图,并配以文字对架构进行简要说明;

3.2 模块简介

架构图中如果有很多模块,需要对各个模块的功能进行简要介绍;

3.3 设计与折衷

设计与折衷是总体设计中最重要的部分;

3.4 潜在风险

4 详细设计

详细设计重点在“详细”

4.1 模块 xx

(有了数据库+接口+流程,别的同学拿到详设文档,基本也能够搞定了)

4.1.1 交互流程

简要的交互可用文字说明,复杂的交互建议使用流程图,交互图或其他图形进行说明

4.1.2 数据库设计

4.1.3 接口形式

5 状态机

5.1 状态机使用

5.1.1 创建状态机

创建完状态机后,状态机有如下类属性

5.1.1.1 类属性

states_map (dict)

transitions (list)

states (list)

5.1.1.2 实例属性

self.model (object)

self.state_field (str)

self.start_value

self.current_state_value

5.1.2 获取当前状态机实例的状态

5.1.3 触发动作

不能从不合法的 state 进行触发动作

其他方法触发动作

5.2 持久化到数据库

5.2.1 简单例子

5.2.2 持久化到 MySQL

5.3 Callbacks

5.3.1 Callbacks when running events

code

操作

5.3.2 callback when entering/exiting states

操作

5.3.3 Callback 之间的关系

当触发 cycle 动作时,输出如下内容

5.3.4 callback 异常对状态变更的影响

假设从状态 green 转变为状态 yellow

  • on_slowdown 异常时,则状态变更失败

  • on_exit_green 异常时,则状态变更失败

  • on_enter_yellow 异常时,则不影响状态变更

6 状态机实践

6.1 状态机

简易状态机图,不考虑异常状态

code

定义数据库字段

使用

状态机父类,支持传三个参数

6.2 状态机在后端架构中位置 -- 个人理解

以管理机器生命周期为例

建表

状态机本身不需要建表,使用类的属性来描述状态,使用方法来描述行为

接口

创建记录接口

状态变更接口

状态变更时有很多流程执行,这里有两种方案

  • 外部触发流程接口,流程接口中进行调用状态变更接口 --------------------------> 【目前先按照这种方式】

  • 外部触发状态变更接口,在触发变更的时候执行 job callback 进行完成流程任务

备注

类比一下

发起一个部署任务 job service_add_unit (部署任务 job 包含多个 task)

6.3 常见问题处理

触发动作时,上一个状态的 exit 检查

假设我们使用 on_exit_{state} 来检查当前状态的任务是否已完成

当我们进行正常变更状态时,检查当前状态的任务是否已完成是必须的

但当我们想要变更为异常状态的时候,则此时需要可直接变更状态,而无需检查之前的任务

目前处理方式

7 传送门

Last updated