akka actor中FSM有限状态机的设计原则

akka actor中的FSM有限状态机的设计原则参考了erlang中的FSM(http://www.erlang.org/documentation/doc-4.8.2/doc/design_principles/fsm.html)

许多应用程序可以利用FSMs来设计,Protocol stacks是其中的一个例子。

我们可以用一个关系集合来描述一个FSM,形式如下:

State(S) x Event(E) -> Actions (A), State(S')
...
这些关系可以被解释为如下含义:

       If we are in state S and the event E occurs, we should perform the actions A and make a transition to the state S'.       如果当前状态处于S,且事件E发生了的话,我们应该执行行为A,并把状态转移到S'

如果用Erlang的gen_fsm行为来编程的话,上述转换规则可以用如下代码来表示:

StateName(Event, StateData) ->
    .. code for actions here ...
    {next_state, StateName', StateData'}
下图用一个简单的FSM来描述”Plain Ordinary Telephony Service“(POTS, 一般的电话服务)

ch_tel_4

电话服务POTS FSM可以用以下gen_fsm行为来描述:

init(A) ->
    {ok, idle, A}.

idle({off_hook, A}, A) ->
    {next_state, getting_number, {A,[]}};
idle({seize, A}, B) when A /= B ->
    {next_state, ringing_b_side, {B, A});
idle(_, A) ->
    {next_state, idle, A}.

getting_number({digit, D}, {A, Seq}) ->
    case ... of
        ... ->
            ...
                {next_state, ringing_a_side, {A, B}};
        ... ->
            ...
                {next_state, getting_number, {A, Seq1}};
        ... ->
            ...
                {next_state, wait_on_hook, A}
    end;
getting_number({on_hook, A}, {A,_}) ->
    {next_state, idle, A}.

ringing_a_side({on_hook, A}, {A, B}) ->
    {next_state, idle, A};
ringing_a_side({answered, B}, {A, B}) ->
    {next_state, speech, {A,B}}.

ringing_b_side({on_hook, A}, {B, A}) ->
    {next_state, idle, B};
ringing_b_side({off_hook, B}, {B, A}) ->
    {next_state, speech, {B, A}}.

speech({on_hook, A}, {A, B}) ->
    {next_state, idle, A};
speech({on_hook, B}, {A, B}) ->
    {next_state, wait_on_hook, A}.

wait_on_hook({on_hook, A}, A) ->
    {next_state, idle, A}.
上述代码只是描述了状态转移。为了增加行为,需要增加以下代码:

getting_number({digit, D}, {A, Seq}) ->
    Seq1 = Seq ++ [D],
    case number_analyser:analyse(Seq1) of
        {user, B} ->
            hw:seize(B, A),
            {next_state, ringing_a_side, {A, B}};
        get_more_digits ->
            {next_state, getting_number, {A, Seq1}};
        invalid_number ->
            hw:send_nasty_tone(A, bad_number_tone),
            {next_state, wait_on_hook, A}
    end;
getting_number({on_hook, A}, {A,_}) ->
    hw:stop_codec(A),
    {next_state, idle, A}.

为了完成这个例子,我们需要把FSM和时间生成器程序打包成behaviour模型,然后增加FSM相关的代码,如下所示:

-module(pots).
-behaviour(gen_fsm).
-export([...]).

start() -> gen_fsm:start(...)

stop() -> gen_fsm:send_all_state_event(...)

on_hook(A) -> gen_fsm:send_event(..., {off_hook, A}).
...
一个FSM的例子:

上面的POTS例子并没有包含全部的细节。下面的小例子是完整的:

-module(test1_fsm).
-behaviour(gen_fsm).

%% interface routines

%% start us up
start() -> gen_fsm:start({local, hello}, test1_fsm, [], []).

%% send a hello -- this will end up in the FSM routines
hello() -> gen_fsm:send_event(hello, {hello, self()}).

%% send a stop this will end up in "handle_event"
stop()  -> gen_fsm:send_all_state_event(hello, stopit).

%% -- interface end

%% This initialisation routine gets called
init(_) ->
    {ok, idle, []}.

%% The state machine
idle({hello, A}, []) ->
    {next_state, one, A}.

one({hello, B}, A) ->
    A ! {hello, B},
    B ! {hello, A},
    {next_state, idle, []}.

%% this handles events in *any* state
handle_event(stopit, AnyState, TheStateData) ->
    {stop, i_shall_stop, []}.   %% tell it to stop


%% This is the finalisation routine - it gets called
%% When we have to stop
terminate(i_shall_stop, TheStateIwasIn, TheStateData) ->
    ok.
 
------------------------------华丽的分割线----------------------------------------------------------------
上面主要讲的是Erlang中的FSM的使用,下面来正式介绍Akka 中的FSM。
 为了展示Akka  FSM特质的大部分特性,我们假设一个Actor接收和存队列大量的爆发式传过来的消息,在消息爆发过后,转发或者清除消息。 

to be continued...........


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值