在actor级别中询问模式在每个级别需要类似的东西?

时间:2015-08-19 21:08:17

标签: scala akka

Monitoring的我的演员层次结构看起来像

    Monitor
    /     \
  Disk    Memory
         /      \
      Remote   Local

Monitor要求其子级角色获取数据等等。 最后,Monitor接收所有数据并将其打印在控制台上(例如)。

仅考虑Memory层次结构,我意识到在ask模式中,层次结构中的调用看起来像

(内存级别)

import ExecutionContext.Implicits.global
  implicit val timeout = Timeout(5 seconds)
  lpMemory <- (lpMemory ? CollectLPMemoryStat).mapTo[MemoryInformation] 

(在远程级别)

  implicit val timeout = Timeout(5 seconds)
  import context.dispatcher
  (remoteActor ? HealthReportRequest).mapTo[MemoryInformation].pipeTo(sender)

所以在ask模式的每个级别,我都需要做4件事

  1. 导入ExecutionContext
  2. 指定Timeout
  3. 转换输出mapTo[MemeoryInformation]
  4. 发回发件人pipeTo(sender)
  5. 如果有更多层次结构,这会很麻烦。

    由于我是AkkaScala堆栈的新手,我正在寻找可以让这些代码更好的想法

    谢谢

1 个答案:

答案 0 :(得分:2)

以下是我要做的事情,以减少开销:

  1. 在单独的特征中提取超时并将其混合到actor中。总而言之,演员们就像其他任何人一样,OOP原则仍然坚持下去。我将定义导入ExecutionContext并指定超时。

    import akka.util.Timeout
    import scala.concurrent.duration._
    
    trait AskEnabled {
        implicit val timeout = Timeout(5 seconds)
        implicit val ec = scala.concurrent.ExecutionContext.Implicits.global
    }
    
  2. 隐式ec值有点像黑客,因为我在写这个答案的过程中得知,从特征中导入的内容实际上并没有传播。所以,这可能有点争议,如果有一天框架不期望ecexecContext例如,但通常会保持代码清洁。

    无论如何,演员看起来像:

    class Actor1 extends Actor with AskEnabled {
    
    val actor2 = context.actorOf(Props[Actor2])
    
    override def receive: Receive = {
     case "send" => {
       val responseFuture = (actor2 ? "request").mapTo[String]
       responseFuture.onSuccess {
         case response: String => println(response)
       }
      }
     }
    }
    
    1. 我相信不需要在远程级别映射然后管道,直接管道应该可以正常工作。 ?的返回类型为Future[Any],但只有Any才会被提升,实际上,当您将其转移时,您实际上不会丢失类型信息。它更多来自Scala的类型推理而不是Akka。然而,在我看来,至少直到TypedActors变得越来越流行之前,整个类型安全事情变得模糊,这是向上倾斜的事情。

      (remoteActor ? HealthReportRequest).pipeTo(sender)

    2. 如果你有更多的层次结构来重用某些功能,那么使用Scala的功能特性,提取该方法(某处)并将其传递给每个actor。函数是一等公民,你可以在构造函数中传递它们,避免重复自己。这是一个粗略的想法,您也可以尝试将其混合到trait中。请查看:Scala Passing Function with Argument