
Akka Actor 的生命週期,正如同一個(gè)狀態(tài)機(jī)一樣,經(jīng)由幾個(gè)Trigger(method invoke)去進(jìn)行狀態(tài)轉(zhuǎn)換。
上圖是Akka官方提供的狀態(tài)機(jī),不過我從實(shí)務(wù)的代碼來(lái)看運(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)來(lái)統(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 的管理模式,是採(cǎi)行一個(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 來(lái)看看他跑的流程:

如果在對(duì)Actor 的操作,有一些很特定的業(yè)務(wù)場(chǎng)景需要綁定相依的物件資源時(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來(lái)操作生命週期轉(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 給拿出來(lái)做後續(xù)處理了~待續(xù)!