斯卡拉 – 阿卡 – 共同服务行为者:识别或扩展
可以说我有一些其他演员服务层演员常用的.例如,存储和检索域对象的注册表服务:
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 } } 我不想明确地将此类注册表的实例传递给可能使用它的所有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 } 我不喜欢这种方式,因为在用户演员初始化之后有一个阶段,当我们不知道系统中是否有一个注册表,因此我们不知道我们是否能够操作. 一个.在初始化时在给定的Actor System中创建Registry actor的实例; 湾通过Extension中的某些方法将此actor返回给需要它的用户. object RegistryKey extends ExtensionKey[RegistryExtension] class RegistryExtesion(system: ExtendedActorSystem) extends RegistryKey { val registry = system.actorOf(Props[Registry],"registry") } 问题是:哪种方法更好,Akka Extesions可以用于此吗? 解决方法
我认为扩展的想法是好的,只要你的注册表演员总是在同一个ActorSystem中.
或者,使用actorSelection(改编自Remote Lookup): class RegistryClient extends Actor { val path = "/path/to/registry/actor" context.setReceiveTimeout(3.seconds) def sendIdentifyRequest(): Unit = context.actorSelection(path) ! Identify(path) def receive = { case ActorIdentity(`path`,Some(ref)) ? context.setReceiveTimeout(Duration.Undefined) context.become(active(ref)) case ActorIdentity(`path`,None) ? throw new RuntimeException("Registry not found") case ReceiveTimeout ? sendIdentifyRequest() } def active(registry: ActorRef): Actor.Receive = { // use the registry } } 这适用于远程或本地演员. 我们来看看扩展解决方案. Actors are created asynchronously.因此,如果actor无法初始化,则在调用actorOf时,扩展构造函数不会失败. 如果你想确定演员未能初始化,那么一种方法就是向演员询问它会响应并等待响应.如果actor无法响应,Await将抛出TimeoutException. class RegistryExtension(system: ExtendedActorSystem) extends Extension { val registry = system.actorOf(Props[Registry],"registry") implicit val timeout: Timeout = Timeout(500.millis) val f = registry ? "ping" // Registry should case "ping" => "pong" Await.result(f,500.millis) // Will throw a TimeoutException if registry fails // to respond } 第一次调用RegistryExtension(system).registry时会抛出TimeoutException. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |