Akka actors 之间的数据共享

Data sharing between Akka actors

基于这个问题Data sharing in Akka我实现了一个简单的 akka 层次结构来在两个参与者之间共享数据:

package playground

import akka.actor.{Actor, ActorRef, ActorSystem, Props}

case object GetFromDb
case object GetList
case object ProcessList

class ParentActor extends Actor {
  var fromDb: List[Int] = List()

  def receive = {
    case GetFromDb =>
      // query the database and replace fromDb with a new list
      fromDb = List(1,2,3)

    case GetList =>
      sender() ! fromDb
  }
}

class ChildActor(parent: ActorRef) extends Actor {
  def receive = {
    case ProcessList =>
      // get the list from the parent
      parent ! GetList
    case fromDb: List[Int] =>
      fromDb.foreach(println)
  }
}

object AkkaDataSharingDriver extends App {

  val system: ActorSystem = ActorSystem("as")
  implicit val ec = system.dispatcher

  val parentActorRef: ActorRef = system.actorOf(Props(new ParentActor()))
  val childActorRef: ActorRef = system.actorOf(Props(new ChildActor(parentActorRef)))

  parentActorRef ! GetFromDb
  parentActorRef ! GetList

  childActorRef ! ProcessList

}

列表值 1、2、3 被打印出来,因此消息 fromDb 被发送到 ChildActor,导致调用此 foreach

case fromDb: List[Int] =>
      fromDb.foreach(println)

但是由于从未明确发送带有 fromDb 的消息,导致

的原因
fromDb.foreach(println)

要调用?它是否以某种方式隐式发送?

child/parent 命名相当混乱,因为此代码中没有 parent/child 关系。最好将它们称为 DbProvider 和 DbClient。

顺序是这样的:

  1. 应用发送 ProcessList 给儿童演员 (childActorRef ! ProcessList)
  2. 子actor发送GetList给父actor(parent ! GetList)
  3. 父 actor 使用 db (sender() ! fromDb)
  4. 回复子 actor
  5. 子actor收到db并打印出来

请注意,此代码中存在竞争条件,理论上 db 可能是 List() 而不是 List(1,2,3)


Akka 中唯一的传递保证是从一个 actor 发送到同一 actor 的两条消息将按照它们发送的顺序进行处理。否则消息可以按任何顺序处理,特别是通过第三方发送的消息可以超过直接发送的消息。

在这种情况下,ProcessList 消息可以由 ChildActor 处理,结果 GetList 消息可以在 [=21= 之前由 ParentActor 处理] 来自应用程序的消息由 ParentActor 处理。如果发生这种情况,对 GetList 的回复将包含默认的 DB 值。