懒洋洋地创建Akka actor层次结构

时间:2013-05-19 10:11:15

标签: scala file-io akka

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

据我了解,只有在其父级存在的情况下才能创建一个actor。懒惰地创建这些层次结构的最佳方法是什么?是否有一个钩子可以用来捕获失败并动态创建actor层次结构,并且这样做有效吗?

这样我就可以将fetchupdatedelete,...消息发送给演员,而akka演员系统可以处理同步问题。然后可以将其扩展到更复杂的演员行为,稍后将使用虚拟文件等概念......

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

  1. 运行context.actorFor(path)如果它返回死信邮箱,请尝试创建actor层次结构。这听起来不是一个好的解决方案。
  2. 将消息发送给root actor,并使用getOrCreateChild方法将其转发给其子节点。但这可能效率低下吗? (或者这就是akka本身在引擎盖下做的......(我应该看看))
  3. 根本没有这样做,只是创建一个actor,它将每条消息委托给动态创建的目录actor,用于所请求文件的每个目录,如堆栈溢出问题"on demand actor get or else create"的答案中所述。这对于捕获目录删除语义不是很好。 (它会更有效率吗?)
  4. [1]我不确定这是否理想,但我认为我应该首先尝试这种方法。另一种方法是为每个目录创建一个actor并将其存储在哈希映射中。

1 个答案:

答案 0 :(得分:2)

首先,演员非常轻量级。您可以在JVM中运行数百万,并且演员本身的占用空间非常小。显然,如果演员有一些可以大记忆的自定义状态,这会发生变化,但演员本身的占地面积非常小。

现在,如果你仍想懒洋洋地实现它们,一种方法可能是拥有一个接收所有初始调用的文件或文件夹主actor。该actor检查系统以查看是否存在一个actor,以便为请求所针对的任何文件夹或文件提供请求。如果没有,主设备会创建它,然后将消息转发给它。如果是这样,它只是将消息转发给它。无需在内存中保留哈希映射,因为ActorSystem本身将为您保留所有ActorRefs,并为您提供查找它们的方法。您只需要一个将文件名/路径等同于actor名称的方法。主人的简化示例可能如下所示:

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%确定那一个。只是想向你抛出一个高级概念,看看这是否是你想要的。