天天看点

Actor生命周期理解

镇图:actor内功心法图

Actor生命周期理解

actor的生命周期可以用hooks体现和控制,下面是默认的actor hooks的方法,我们可以选择性的进行重写:

每个hooks,在不同的策略下调用次数及顺序是不同的,那什么是策略?:

策略,比如restart,实际上就是执行了一系列的方法包括:prerestart,postrestart

start策略,调用prestart hook,一般用于初始化资源.在创建一个actor的时候,会调用构造函数,之后调用prestart,那这两个方法有什么区别呢,资源初始化是放在构造函数,还是放在prestart里面呢?在restart策略里面会详细介绍。

Actor生命周期理解

poststop hook 一般用于回收资源。actor在被调用poststop之前,会将邮箱中剩下的message处理掉(新的消息变成死信了)。actor是由uid和path来唯一标识的,也就是说actorref也是通过uid和path来定位。在actor被stop之后,新的actor是可以用这个path的,<code>但是旧的actorref是不能用的,因为uid不一样。</code>

Actor生命周期理解

restart策略是最为复杂的一种情况,先上个图:

Actor生命周期理解

在默认情况下,restart策略会:

actor被挂起

调用旧实例的 supervisionstrategy.handlesupervisorfailing 方法 (缺省实现为挂起所有的子actor)

调用prerestart方法,从上面的源码可以看出来,prerestart方法将所有的children stop掉了!(stop动作,大家注意!),并调用poststop回收资源

调用旧实例的 supervisionstrategy.handlesupervisorrestarted 方法 (缺省实现为向所有剩下的子actor发送重启请求)

等待所有子actor终止直到 prerestart 最终结束

再次调用之前提供的actor工厂创建新的actor实例

对新实例调用 postrestart

恢复运行新的actor

<code>restart策略,和stop策略有什么不同的地方?</code>

stop策略会调用poststop(),restart策略也会调用poststop(),但是restart策略不是通过stop策略来停止旧的actor,uid和path都没变。也就是说,在被restart之后,不用重新获取actorref.

<code>prerestart hook有什么特别之处?</code>

默认的prerestart hook会将所有的children通过stop策略停止,这个时候children就是通过stop策略-&gt;start策略启动的,而不是被递归restart.那有什么影响?如果有外部的actor持有旧的chidren actorref,那这个ref就是不能用的,因为虽然path是对的,但是uid已经变了!

<code>postrestart hook有什么特别之处?</code>

默认postrestart是调用prestart(),这样在重启的过程中,构造函数和prestart方法都会被重新调用,<code>如果有个资源只想初始化一次,那么就必须重写掉这个方法</code>.所以一般创建children是放在prestart里面。

<code>被重启后,如何继承旧的actor的状态?</code>

通过将state转储到:

非jvm级别的crash,使用静态类保存状态