如何动态检查演员的类型

How to dynamically check type of an actor

这是一个关于使用akka actor系统开发的一般问题。

我知道,它牺牲了静态类型检查以获得更大的灵活性,这不是问题所在。 Java一路做同样的事情

但我想至少动态检查 ActorRef 的兼容性。我搜索了一些方法,比如 actorRef.asInstanceOf[ActorType]。这种方法应该为通过消息传递的 actorRef 提供验证。它将允许安全的应用程序开发。但是我找不到进行任何类型检查的方法。甚至不可能检查 actorRef 是否对应于给定的 Props。

这个任务在 akka 应用程序中通常是如何解决的?有没有第三方动态检测工具?

ActorRef的目的是完全抽象收件人。向它发送消息绝对不能保证所发送消息的响应甚至适用性。收件人可以丢弃消息、路由消息、存储消息或处理消息。任何关于处理和导致发出可能的响应消息的合同完全是非正式协议。

现在,在静态类型的环境中,这听起来像是要放弃很多东西,但它提供了一种编程模型,它带来了自己的一系列优势,根据他们的设计,您在发送和接收消息时假设消息将被处理,但不知道它们将在何时何地被处理。

关于在 akka 应用程序中通常如何解决此任务是通过配置 and/discovery。可接受消息的契约通常放在协议对象中,而这些消息的有效接收者要么在创建时注入到调用 Actor 中,要么通过某些 DiscoveryProtocol(本身隐藏在 ActorRef 后面)进行查询

假设您有一个 UserRepository 想要查询,您将创建这样的协议:

case class User(id: Int, ... )

object UserRepositoryProtocol {
  case class GetUser(userId: Int)
}

此外,我们假设 UserRepositoryActorRef 没有被注入,但因为它只是您的演员可能使用的许多 服务 之一通过一般 Discovery 服务被发现:

object DiscoveryProtocol {
   case class Discover(type: String)
   case class Discovered(type: String, ref: ActorRef)
}

现在您可以像这样获取用户:

(discoveryRef ? Discover("UserRepository")).flatMap {
  case Discovered("UserRepository",repository) =>
    (repository ? GetUser(id)).map {
       case user:User => // do something with the user
    }
}

以上内容将发现和调用浓缩为一系列 ask 操作。您可能希望缓存发现的 ref 和/或将检索到的用户交给其他正在做这项工作的 Actor,打破每个 '?'在相同或不同的演员中进入 ! 和匹配的 receive

最后一点说明了演员模型的力量。在传统的 request => response 模型中,requestorresponse 的接收者必须是相同的,仅凭函数签名,但在演员模型中,您可以从一个演员发送, 产生一个 worker 来处理响应等

假设演员不仅被封装在演员引用后面,而且演员的物理位置也是未知的。参与者可以 运行 在另一台物理服务器或 VM 上。您不能在另一个 VM 中的对象上调用 instanceOf - 那么您怎么能期望获得演员的 class?

现在,在构建时,我建议您通过 Akka 的位置透明性考虑所有参与者都是远程的。 (http://doc.akka.io/docs/akka/snapshot/general/remoting.html) 如果您假设所有参与者都是远程的,突然之间您对您的设计的看法会有所不同。将 Akka 视为一个分发工具包——这是它的主要好处!

如果您试图在运行时反映演员,那么您的设计可能有问题。相反,您需要知道参与者可以接受和响应哪些消息。

如果你真的想知道演员能做什么和不能做什么,那么你可以考虑对某种 "Accepts" 方法进行建模,演员会用所描述的当前版本回复 API 例如,actor 实现的 - 通过这种方式,您的客户端和服务器可以来回讨论在运行时动态支持哪些功能等。

我希望这对讨论有所贡献 - 请记住始终将演员视为 运行 其他地方的东西,您将进行适当的设计。这样做的好处是,如果您的用户群意外激增,您将能够以非常小的努力扩展您的应用程序!