1. 有限状态机
首先了解下状态机的几个概念
- 状态(state),在状态机中状态是已知的,且有限的
- 事件(Event),一个状态机实例接受事件,感觉当前所处的状态来进行不同的处理
- 变换器(Transition),定义事件在具体state下的,处理流程,bing并输出处理后的state
从上面介绍可以看出,在状态机中,所有的状态,事件和变换器都是事先定义好的,为了更好理解状态机的实现,我们从由浅入深,选取已有的实现,讲解状态机的实现与应用
2. mina 状态机实现
在介绍mina状态机时,我们先介绍几个基本概念:
1. StateMachine 一个完整的状态机
2. State,状体机中的某个状态
3. Transition,状态机的转换器,判断当前状态以及事件,选取对应的Transition,经过Transition变换后,会变更当前StateContext的状态
4. StateContext,唯一当前状态机的上下文,存储当前事件所属的状态,以及一些通用的属性数据
5. Event,表示某个事件
具体的关系图:
从上图可以看出一个实体的状态并不是维护在StateMachine中,而是维护在StateContext中,所以需要自己独立维护每个实体的context才能做到多状态机的并存,StateMachine只关注状态逻辑的处理
StateMachine初始化完成后,会包含所有的state。而state会包含前置状态是本state的Transition变换器,如下图所示可以把Transition当作两个state的连线
具体的入口在StateMachine.handle(Event event),状态机的handle方法会接收带有StateContext的事件,具体逻辑如下:
- handle接收到event事件后,将事件存到对列中
- 从队列中取出一个event,并从该event中取出StateContext
- 从StateContext取出当前的state,然后用当前state中的Transition来处理该event,Transition处理完后得到新的state,并将state更新到StateContext中
伪代码流程如下:
- StateMachine.handle入口方法,只保留核心逻辑代码
public void handle(Event event) {
//将事件event加入到eventQueue队列中
LinkedList<Event> eventQueue = eventQueueThreadLocal.get();
eventQueue.addLast(event);
//处理消息队列
processEvents(eventQueue);
}
- 处理队列中的事件
private void processEvents(LinkedList<Event> eventQueue) {
while (!eventQueue.isEmpty()) {
Event event = eventQueue.removeFirst();
StateContext context = event.getContext();
//取出事件中的StateContext中的当前状态,然后传递进行处理
handle(context.getCurrentState(), event);
}
}
- 处理单个事件,具体逻辑是取出state中的所有Transition,然后将事件进行处理,直到处理成功,则返回
private void handle(State state, Event event) {
StateContext context = event.getContext();
for (Transition t : state.getTransitions()) {
if (t.execute(event)) {
setCurrentState(context, t.getNextState());
return;
}
}
}
mina状态机只是简单的实现,希望让大家对状体机有一个初步的了解,同时mina也有好多特性并不支持,如:
- 复杂状态机流程的实现
在Transition转换器中已经定义好了匹配的输入state和event,针对输出只有一个状态,并不能动态根据条件选择
- 状态机的持久化
在一个状态机中要走完所有状态,可能需要一段时间,假如服务重启,会丢失状态机中的数据,同时mina中状态机并没有终止状态,所以状态机也没有明确的终止点
上面流程代码中,并不包含异常的处理,并发的控制,如有兴趣可以看源码,具体引入包查看
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-statemachine</artifactId>
<version>2.1.4</version>
</dependency>
3. 具体应用
- 对于具体的应用可以看下阿里云的服务编排产品,一次服务的编排可以认为是一个状态机模版,定义了整个流程,通过推动状态变更来推动流程,有兴趣可以看下,阿里云服务编排
- 有兴趣的可以看下seata saga模式分布式事务的实现,也采用了状态机的思想实现服务编排
参考: