Akka Actor 的生命週期,正如同一個狀態機一樣,經由幾個Trigger(method invoke)去進行狀態轉換。
上圖是Akka官方提供的狀態機,不過我從實務的代碼來看運行的狀態改動會更貼切一點:
Actor 在運行時,Akka framework在對於Actor被初始化時會引發兩個CallBack
preStart()
postStop()
由於Akka 已經有提供了基類(base abstract class)的template pattern 提供基礎的運行代碼,所以我Override 這兩個method:
Override preStart() , postStop() callBack methods在初始化Actor 的時候,我們不能很單純的把它當成物件直接去new ,原因是Actor 是仰賴於整個Akka framework 做生命週期管控,Akka提供了 ActorRef 機制(你可以想像他是actor instance access interface),透過ActorRef 對instance 做查找與執行訊息傳遞的行為 !
這樣的基礎限制條件,其實跟很多知名的容器體系下的元件使用模式理念相同,譬如我們不能直接去New EJB Instance,不能直接去New一個已經有對Spring framework 重度相依的 Bean instance一樣。
Try new instance by new syntax but would be error.上例當中直接new ,執行結果如下:
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 ‘actorOf’ factory methods to create a new actor. See the documentation.
這是因為Akka framework 是以factory pattern(by actorOf method)來統一實現Actor 初始化的做法,正確的作法應該是利用Akka system context去創建你需要的Actor instance。
Akka create actor with akka system context執行啟動後,可以看到一個類似於Web URI 的位址連結
Callback invoked[akka://sample/user/test]
Akka 對於Actor 的管理模式,是採行一個樹狀的地址模型,每一個actor 都能創建出他的子Actor 或相關連操作的 Actor,每一個上層的Actor都有責任與義務去照顧與監控他底下的子Actor或相依的Actor,這樣的樹狀體系體現在URI上,就還蠻容易理解了。
從上述的log當中確實看到,Actor 物件在初始化之後,會自動地進行preStart()/postStop(),為了能更精確理解建構的流程,我刻意添加了default constructor 來看看他跑的流程:
run with constructor如果在對Actor 的操作,有一些很特定的業務場景需要綁定相依的物件資源時(譬如建構子直接注入 external repository, 或者注入 external service gateway access point),可以在這幾個method 當中特別去留意狀態變化,有時候問題有機會在這幾個時機點去幫忙做除錯的檢驗。
接著看看如何停止Actor :
Akka 在Java 方面的實現是透過 Actor receive command時, 基於 actorContext 停止Actor
Stop Actor via actorContext寫個測試代碼運行看看
demo stop Actor in Junit運行結果
testing result可以看到Actor實體確實正確的被停止了,但是因為我試圖要做驗證檢查Actor status,Akka framewok抗議了,因為我試圖要從ActorSystem 當中去獲取還在運行狀態的Actor,但是因為已經中斷了(不存在這樣的一個running actor),所以會拋出illegalActorStateException。
Actor lifecycle trait method define特別一提,Akka 在Java 的實現上,僅提供了透過receive command ,藉由actorContext 執行stop actor 的做法,但是在Scala上,則可以直接在外部操作Stop 的這個trait method直接停掉Actor,這是蠻大的差異的。
上圖中,很明確地看到了Akka 的設計原則是只能夠透過內部context來操作生命週期轉換,不過希望只是我還沒找到在Java上的外部停止Actor的做法,不然只能基於Command 的操作還真是有些不方便。
前面測試理解到假設Actor Instance已經是進入到terminated的狀態,若我們試圖再一次對他送信息,看看系統會有啥反應?
reSendMessageToAnTerminatedActorActorSystem偵測到這個actor的狀態已經是不可觸及的,於是把信息塞入到DeadLetter 裡頭去 !
DeadLetter environment接續,就是該思考怎麼把Dead Letter 給拿出來做後續處理了~待續!
网友评论