AKKA Actor創建


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 封裝。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM