Akka - 共同服务人员:识别或扩展

Sei*_*ert 7 scala identify actor akka

可以说我有一些其他演员服务层演员常用的.例如,存储和检索域对象的注册表服务:

case class DomainObject(id: UUID)

class Registry extends akka.actor.Actor {
  def receive: Receive = {
    case o: DomainObject => store(o) // save or update object

    case id: UUID => sender ! retrieve(id) // retrieve object and send it back
  }
}
Run Code Online (Sandbox Code Playgroud)

我不想将此类注册表的实例明确传递给可能使用它的所有actor.而不是它,我希望他们能够以某种方式"找到"它.

为此我可以想到两个解决方案:

  1. Identify消息:每个注册表用户actor都知道来自某些配置的注册表actor名称,并且能够向其发送标识消息.之后AgentIdentity被收回的消息,我们是好去:

    val registryName = ... // some name
    val registryId = ... // some id
    var registry = _
    
    def preStart() {
      context.actorSelection(registryName) ! Identify(registryId)
    }
    
    def receive: Receive = {
      case ActorIdentity(`registryId`, ref) => registry = ref
    }
    
    Run Code Online (Sandbox Code Playgroud)

    我不喜欢这种方式,因为在用户演员初始化之后,当我们不知道系统中是否存在注册表并且因此不知道我们是否能够操作时,存在阶段.

  2. Akka扩展:我可以创建一个扩展,它将:

    一个.在初始化时在给定的Actor System中创建Registry actor的实例;

    湾 通过Extension中的某些方法将此actor返回给需要它的用户.

    object RegistryKey extends ExtensionKey[RegistryExtension]
    
    class RegistryExtesion(system: ExtendedActorSystem) extends RegistryKey {
      val registry = system.actorOf(Props[Registry], "registry")
    }
    
    Run Code Online (Sandbox Code Playgroud)

问题是:哪种方法更好,Akka Extesions可以用于此吗?

sou*_*ica 3

我认为扩展的想法是一个很好的想法,只要您的注册表参与者始终位于相同的ActorSystem.

\n\n

或者,使用actorSelection(改编自Remote Lookup):

\n\n
class RegistryClient extends Actor {\n  val path = "/path/to/registry/actor"\n  context.setReceiveTimeout(3.seconds)\n\n  def sendIdentifyRequest(): Unit =\n    context.actorSelection(path) ! Identify(path)\n\n  def receive = {\n    case ActorIdentity(`path`, Some(ref)) \xe2\x87\x92\n      context.setReceiveTimeout(Duration.Undefined)\n      context.become(active(ref))\n    case ActorIdentity(`path`, None) \xe2\x87\x92\n      throw new RuntimeException("Registry not found")\n    case ReceiveTimeout \xe2\x87\x92 sendIdentifyRequest() \n  }\n\n  def active(registry: ActorRef): Actor.Receive = {\n    // use the registry\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这适用于远程或本地参与者。

\n\n

让我们看看扩展解决方案。Actor 是异步创建的actorOf因此,如果参与者无法初始化, 您的扩展构造函数在调用时不会失败。

\n\n

如果您想确定 Actor 未能初始化,那么一种了解方法是向askActor 提供它将响应的内容和Await响应。如果参与者未能响应,则会Await抛出 a 。TimeoutException

\n\n
class RegistryExtension(system: ExtendedActorSystem) extends Extension {\n  val registry = system.actorOf(Props[Registry], "registry")\n  implicit val timeout: Timeout = Timeout(500.millis)\n  val f = registry ? "ping"    // Registry should case "ping" => "pong" \n  Await.result(f, 500.millis)  // Will throw a TimeoutException if registry fails \n                               // to respond\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

当你第一次调用时会TimeoutException被抛出。RegistryExtension(system).registry

\n