2

我想创建可以从文件系统提供资源的参与者。理想情况下 [1] 我希望每个目录和每个文件都有一个演员。但我不想创建整个演员树层次结构,因为我想尽可能地节省内存和资源。

据我了解,只有在其父级存在时才能创建演员。懒惰地创建这些层次结构的最佳方法是什么。是否有一个钩子可以用来捕捉失败并动态创建参与者层次结构,并且有效地做到这一点?

有了这个,我就可以向演员发送fetch, update, delete, ... 消息,而 akka 演员系统将因此处理同步问题。然后可以通过虚拟文件等概念将其扩展到更复杂的参与者行为......

我能想到的一些可能的解决方案:

  1. 运行context.actorFor(path),如果它返回死信邮箱,则尝试创建参与者层次结构。这听起来不是一个好的解决方案。
  2. getOrCreateChild将消息发送给根actor,并通过某种方法将其转发给它的子actor 。但这可能效率低下吗?(或者这就是akka本身在引擎盖下所做的事情......(我应该看看))
  3. 根本不这样做,只需创建一个actor,将每条消息委托给为所请求文件的每个目录动态创建的目录actor,如堆栈溢出问题“on demand actor get or else create”的答案中所述。这对于捕获目录删除语义不是很好。(会不会更有效率?)

[1] 我不确定这是否理想,但我认为我应该先尝试这种方法。另一种方法是为每个目录创建一个参与者并将其存储在哈希映射中。

4

1 回答 1

2

首先,演员非常轻量级。您可以在 JVM 中运行数以百万计的参与者,而参与者本身的占用空间非常小。显然,如果 actor 有一些自定义状态可以占用大量内存,那么这种情况就会改变,但 actor 本身的占用空间非常小。

现在,如果您仍想延迟实现它们,一种方法可能是让单个文件或文件夹主参与者接收所有初始调用。该参与者检查系统以查看参与者是否已经存在来为请求所针对的任何文件夹或文件的请求提供服务。如果没有,主节点创建它,然后将消息转发给它。如果是这样,它只是将消息转发给它。无需在内存中保留哈希图,因为它ActorSystem本身将为您保存所有内容并ActorRefs为您提供查找它们的方法。您只需要一种将文件名/路径等同于演员名称的方法。一个过度简化的 master 示例可能如下所示:

case class Fetch(path:String)
class FileMaster extends Actor{
  def receive = {
    case msg @ Fetch(path) =>
      val ref = lazyFindActor[FileHandler](path)
      ref.forward(msg)
  }

  def lazyFindActor[T <: Actor: Manifest](name:String) = {
    val ref = context.actorFor(name)
    if (ref == context.system.deadLetters){
      context.actorOf(Props[T], name)
    }
    else{
      ref
    }
  } 
}

所做lazyFindActor的只是检查路径的actor是否已经创建并启动。如果是这样,它会转发给它。如果没有(deadLetters不幸的是,我没有看到更好的方法来检查演员是否存在),它会在主人的监督下创建一个,然后转发给它。下次进入相同路径时,它将使用预先存在的Actor.

您可能需要做一些工作,将文件路径语法转换为可用于演员名称的内容(因为 akka 已经使用分层文件路径,如演员路径的结构),但我对此不是 100% 确定一。只是想向您抛出一个高级概念,看看这是否是您想要的。

于 2013-05-19T11:02:09.207 回答