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