Akka Actor 的生命週期缓窜,正如同一個(gè)狀態(tài)機(jī)一樣,經(jīng)由幾個(gè)Trigger(method invoke)去進(jìn)行狀態(tài)轉(zhuǎn)換谍咆。
上圖是Akka官方提供的狀態(tài)機(jī)禾锤,不過我從實(shí)務(wù)的代碼來看運(yùn)行的狀態(tài)改動(dòng)會(huì)更貼切一點(diǎn):
Actor 在運(yùn)行時(shí),Akka framework在對(duì)於Actor被初始化時(shí)會(huì)引發(fā)兩個(gè)CallBack
preStart()
postStop()
由於Akka 已經(jīng)有提供了基類(base abstract class)的template pattern 提供基礎(chǔ)的運(yùn)行代碼摹察,所以我Override 這兩個(gè)method:
在初始化Actor 的時(shí)候恩掷,我們不能很單純的把它當(dāng)成物件直接去new ,原因是Actor 是仰賴於整個(gè)Akka framework 做生命週期管控供嚎,Akka提供了 ActorRef 機(jī)制(你可以想像他是actor instance access interface)黄娘,透過ActorRef 對(duì)instance 做查找與執(zhí)行訊息傳遞的行為 !
這樣的基礎(chǔ)限制條件,其實(shí)跟很多知名的容器體系下的元件使用模式理念相同克滴,譬如我們不能直接去New EJB Instance逼争,不能直接去New一個(gè)已經(jīng)有對(duì)Spring framework 重度相依的 Bean instance一樣。
上例當(dāng)中直接new 劝赔,執(zhí)行結(jié)果如下:
akka.actor.ActorInitializationException: You cannot create an instance of [solid.humank.actor.ExplainActorLifeCycle] explicitly using the constructor (new). You have to use one of the ‘a(chǎn)ctorOf’ factory methods to create a new actor. See the documentation.
這是因?yàn)锳kka framework 是以factory pattern(by actorOf method)來統(tǒng)一實(shí)現(xiàn)Actor 初始化的做法誓焦,正確的作法應(yīng)該是利用Akka system context去創(chuàng)建你需要的Actor instance。
執(zhí)行啟動(dòng)後着帽,可以看到一個(gè)類似於Web URI 的位址連結(jié)
[akka://sample/user/test]
Akka 對(duì)於Actor 的管理模式杂伟,是採行一個(gè)樹狀的地址模型移层,每一個(gè)actor 都能創(chuàng)建出他的子Actor 或相關(guān)連操作的 Actor,每一個(gè)上層的Actor都有責(zé)任與義務(wù)去照顧與監(jiān)控他底下的子Actor或相依的Actor赫粥,這樣的樹狀體系體現(xiàn)在URI上观话,就還蠻容易理解了。
從上述的log當(dāng)中確實(shí)看到傅是,Actor 物件在初始化之後匪燕,會(huì)自動(dòng)地進(jìn)行preStart()/postStop()蕾羊,為了能更精確理解建構(gòu)的流程喧笔,我刻意添加了default constructor 來看看他跑的流程:
如果在對(duì)Actor 的操作,有一些很特定的業(yè)務(wù)場景需要綁定相依的物件資源時(shí)(譬如建構(gòu)子直接注入 external repository, 或者注入 external service gateway access point)龟再,可以在這幾個(gè)method 當(dāng)中特別去留意狀態(tài)變化书闸,有時(shí)候問題有機(jī)會(huì)在這幾個(gè)時(shí)機(jī)點(diǎn)去幫忙做除錯(cuò)的檢驗(yàn)。
接著看看如何停止Actor :?
Akka 在Java 方面的實(shí)現(xiàn)是透過 Actor receive command時(shí)利凑, 基於 actorContext 停止Actor
寫個(gè)測(cè)試代碼運(yùn)行看看
運(yùn)行結(jié)果
可以看到Actor實(shí)體確實(shí)正確的被停止了浆劲,但是因?yàn)槲以噲D要做驗(yàn)證檢查Actor status,Akka framewok抗議了哀澈,因?yàn)槲以噲D要從ActorSystem 當(dāng)中去獲取還在運(yùn)行狀態(tài)的Actor牌借,但是因?yàn)橐呀?jīng)中斷了(不存在這樣的一個(gè)running actor),所以會(huì)拋出illegalActorStateException割按。
特別一提膨报,Akka 在Java 的實(shí)現(xiàn)上,僅提供了透過receive command 适荣,藉由actorContext 執(zhí)行stop actor 的做法现柠,但是在Scala上,則可以直接在外部操作Stop 的這個(gè)trait method直接停掉Actor弛矛,這是蠻大的差異的够吩。
上圖中,很明確地看到了Akka 的設(shè)計(jì)原則是只能夠透過內(nèi)部context來操作生命週期轉(zhuǎn)換丈氓,不過希望只是我還沒找到在Java上的外部停止Actor的做法周循,不然只能基於Command 的操作還真是有些不方便。
前面測(cè)試?yán)斫獾郊僭O(shè)Actor Instance已經(jīng)是進(jìn)入到terminated的狀態(tài)万俗,若我們?cè)噲D再一次對(duì)他送信息湾笛,看看系統(tǒng)會(huì)有啥反應(yīng)?
ActorSystem偵測(cè)到這個(gè)actor的狀態(tài)已經(jīng)是不可觸及的,於是把信息塞入到DeadLetter 裡頭去 !
接續(xù)该编,就是該思考怎麼把Dead Letter 給拿出來做後續(xù)處理了~待續(xù)!