我怎样才能从接待员那里得到 ActorRef 以便我的演员可以向那个演员发送消息

How can I get the ActorRef from the Receptionist so my actor can send messages to that actor

所以我有 2 个演员,ClientInMaker

我需要在 ClientIn 中引用 Maker,这样我就可以将 ClientIn 收到的一些消息转发给 Maker

我将 Maker 添加到 receptionist,但由于 clientIn 是第一个创建的,而 maker 第二个我不确定如何查询以获取 actorRef .

实际上我只是很困惑我现在如何查询接待员以便 clientIn 将获得对 Maker actor 的引用。

这是我的:

// 守护actor构造函数:

Behaviors.setup[Any] { context =>
    implicit val ec: ExecutionContext = context.executionContext

    val system = context.system

    val clientIn = context.spawn(ClientIn(), "ClientIn")

    val maker = context.spawn(Maker(clientOut), "mmaker")

    ....

}    

ClientIn.scala:

object ClientIn {
  sealed trait ClientInCommand
  case class Watch(symbol: String) extends ClientInCommand
  case class Command(value: String) extends ClientInCommand
  private case class ListingResponse(listing: Receptionist.Listing)
      extends ClientInCommand

  def apply(): Behavior[ClientInCommand] = {

    Behaviors.setup { context =>
      context.log.info(s"ClientIn starting...${context.self}")

      val listingResponseAdapter =
        context.messageAdapter[Receptionist.Listing](ListingResponse.apply)

      var maker: Option[ActorRef[Maker.MMCommand]] = None

      Behaviors.receiveMessage[ClientInCommand] {
        case Watch(symbol) =>
          context.log.info(s"ClientIn watch message received..$symbol")
          Behaviors.same
        case Command(value) =>
          context.log.info(s"ClientInCommand.Command with value:$value")

          // TODO: Maker ! RecieveCommand(value)
          Behaviors.same
        case ListingResponse(Maker.makerKey.Listing(listings)) =>
          maker = Some(listings.head)
          Behaviors.same

      }
    }

  }
}      

Maker.scala:

object Maker {
  val makerKey = ServiceKey[MMCommand]("makerKey")

  sealed trait MMCommand
  case object Startup extends MMCommand
  case object Shutdown extends MMCommand

  def apply(): Behavior[MMCommand] = {

    Behaviors.setup { context =>

      context.system.receptionist ! Receptionist.Register(
        makerKey,
        context.self
      )

      Behaviors.receiveMessage[MMCommand] {
        case Startup =>
          context.log.info("Maker startup message received..")
          Behaviors.same
        case Shutdown =>
          context.log.info("Maker shutdown message received..")
          Behaviors.same
      }

    }

  }
}

您可以向接待员发送 Receptionist.Subscribe(Maker.makerKey) 消息,如 Actor discovery 上的 Akka 文档所述:

context.system.receptionist ! Receptionist.Subscribe(Maker.makerKey, listingResponseAdapter)

引用文档:

It will send Listing messages to the subscriber, first with the set of entries upon subscription, then whenever the entries for a key are changed.

这允许它接收制造商 ActorRef,即使它在生成 ClientIn 演员后向接待员注册也是如此。但是,原则上 ClientIn 可能会在此之前收到其他消息,例如 Command。它将需要处理这些情况,可能通过 stashing 或删除命令直到 Maker 被注册。

在这个具体的例子中,通过先生成 Maker 并将它的 ActorRef 传递给 ClientIn.apply 来避免这个要求会更简单:

val maker = context.spawn(Maker(), "mmaker")
val clientIn = context.spawn(ClientIn(maker), "ClientIn")

然后,在ClientIn

def apply(maker: ActorRef[Maker.MMCommand]): Behavior[ClientInCommand] = {
  Behaviors.setup { context =>
    context.log.info(s"ClientIn starting...${context.self}")
    Behaviors.receiveMessage[ClientInCommand] {
      case Watch(symbol) =>
        context.log.info(s"ClientIn watch message received..$symbol")
        Behaviors.same
      case Command(value) =>
        context.log.info(s"ClientInCommand.Command with value:$value")
        maker ! Maker.ReceiveCommand(value)
        Behaviors.same
    }
  }
}

请注意,从 spawn 返回的 ActorRef 能够立即接收消息,即使 actor 尚未完全初始化。