镇图:actor内功心法图
actor的生命周期可以用hooks体现和控制,下面是默认的actor hooks的方法,我们可以选择性的进行重写:
每个hooks,在不同的策略下调用次数及顺序是不同的,那什么是策略?:
策略,比如restart,实际上就是执行了一系列的方法包括:prerestart,postrestart
start策略,调用prestart hook,一般用于初始化资源.在创建一个actor的时候,会调用构造函数,之后调用prestart,那这两个方法有什么区别呢,资源初始化是放在构造函数,还是放在prestart里面呢?在restart策略里面会详细介绍。
poststop hook 一般用于回收资源。actor在被调用poststop之前,会将邮箱中剩下的message处理掉(新的消息变成死信了)。actor是由uid和path来唯一标识的,也就是说actorref也是通过uid和path来定位。在actor被stop之后,新的actor是可以用这个path的,<code>但是旧的actorref是不能用的,因为uid不一样。</code>
restart策略是最为复杂的一种情况,先上个图:
在默认情况下,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策略->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,使用静态类保存状态