Actor 類定義
Actor 類需要繼承AbstractActor類
實現createReceive方法,綁定各類actor收到不同類型消息對應處理不同業務邏輯
默認提供了ReceiveBuilder類輔助創建 Receive
對actorOf的調用返回ActorRef的實例。這是 Actor 實例的句柄,也是與之交互的唯一方法。
ActorRef是不可變的,並且與它所表示的 Actor 有一對一的關系。ActorRef也是可序列化的, 序列化通過網絡發送它,並在遠程主機上使用它,並且它仍然在網絡上表示原始節點上的同一個 Actor。
Actor的層級關系
Actor的層級關系類似樹模式
誰創建誰管理原則:
ActorSystem 創建就由ActorSystem負責監控管理(重啟,異常,恢復等)
Actor中創建另外的Actor,則創建者看做為父級,負責監控管理它創建出來的actor
Actor 生命周期
actorOf -> preStart -> start -> receive -> stop -> postStop
另外:
reRestart()默認行為是在重啟(restarting)之前,它會終止所有的children actors(這個過程是遞歸的)。postRestart()則發生在重啟成功之后。當然,方法都可以重寫這兩個方法以改變其行為。
Props
Props 創建 Actor 的配置選項,推薦在actor類提供一個通用的props方法來創建
注意:
1,同一個akka集群中創建的actor 實例 name不能重復,不然會報InvalidActorNameException異常
2,ActorSytem同一個集群,各節點的ActorSytem name必須相同
3,不允許自行new創建actor實例
如果直接new Actor實例方式創建Actor會報ActorInitializationException錯誤
示例:
<!-- Gradle --> dependencies { compile group: 'com.typesafe.akka', name: 'akka-actor_2.12', version: '2.5.21' }
package akka.demo.actor import akka.actor.AbstractActor import akka.actor.ActorRef import akka.actor.Props import akka.japi.pf.ReceiveBuilder import org.slf4j.LoggerFactory /** ** created by tankx ** 2019/9/10 **/ class HelloActor(val name: String) : AbstractActor() { //創建子actor private val childActor: ActorRef = context.actorOf(ChildActor.props()) companion object { private val log = LoggerFactory.getLogger(HelloActor::class.java) //提供靜態通用對外的props fun props(name: String): Props { //return Props.create(HelloActor::class.java, name)//默認方式 return Props.create(HelloActor::class.java) { HelloActor(name) } } } override fun preStart() { log.info("preStart") super.preStart() } override fun postStop() { log.info("postStop") super.postStop() } override fun createReceive(): Receive { return ReceiveBuilder.create().matchAny(::onReceive).build() } fun onReceive(msg: Any) { log.info("$name say: $msg") log.info("sender:{}", sender.toString()) } }
package akka.demo.actor import akka.actor.AbstractActor import akka.actor.Props import akka.japi.pf.ReceiveBuilder import org.slf4j.LoggerFactory /** ** created by tankx ** 2019/9/10 **/ class ChildActor : AbstractActor() { private val log = LoggerFactory.getLogger(ChildActor::class.java) companion object { fun props(): Props { return Props.create(ChildActor::class.java) } } override fun preStart() { log.info("preStart") super.preStart() } override fun postStop() { log.info("postStop") super.postStop() } override fun createReceive(): Receive { return ReceiveBuilder.create().matchAny(::onReceive).build() } fun onReceive(msg: Any) { log.info("onReceive: $msg") } }
創建ACTOR,並發消息
val system = ActorSystem.create("akka-system") val actorRef = system.actorOf(HelloActor.props("aa"), HelloActor::class.java.simpleName) actorRef.tell("hi world", ActorRef.noSender()) //給actor發消息
依賴注入
如果有依賴注入的情況,需要傳入依賴項來構建Actor
示例:
package akka.demo.actor import akka.actor.Actor import akka.actor.IndirectActorProducer /** ** created by tankx ** 2019/9/11 ** 如果有依賴注入方式可使用當前的工廠類的方式進行創建actor **/ class ActorFactory(var applicationContext: String) : IndirectActorProducer { override fun actorClass(): Class<out Actor> { return HelloActor::class.java } override fun produce(): Actor { return HelloActor(applicationContext) } }
創建方式:
val actorFactoryRef = system.actorOf(Props.create(ActorFactory::class.java, "aaa"), "aaa") actorFactoryRef.tell("hi factory", ActorRef.noSender())
總結:
AKKA創建Actor需要嚴格按照推薦的方式去創建,以避免破壞Actor 封裝。