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件事
ExecutionContext
Timeout
mapTo[MemeoryInformation]
pipeTo(sender)
如果有更多层次结构,这会很麻烦。
由于我是Akka
和Scala
堆栈的新手,我正在寻找可以让这些代码更好的想法
谢谢
答案 0 :(得分:2)
以下是我要做的事情,以减少开销:
在单独的特征中提取超时并将其混合到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
}
隐式ec
值有点像黑客,因为我在写这个答案的过程中得知,从特征中导入的内容实际上并没有传播。所以,这可能有点争议,如果有一天框架不期望ec
但execContext
例如,但通常会保持代码清洁。
无论如何,演员看起来像:
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)
}
}
}
}
我相信不需要在远程级别映射然后管道,直接管道应该可以正常工作。 ?
的返回类型为Future[Any]
,但只有Any
才会被提升,实际上,当您将其转移时,您实际上不会丢失类型信息。它更多来自Scala的类型推理而不是Akka。然而,在我看来,至少直到TypedActors变得越来越流行之前,整个类型安全事情变得模糊,这是向上倾斜的事情。
(remoteActor ? HealthReportRequest).pipeTo(sender)
如果你有更多的层次结构来重用某些功能,那么使用Scala的功能特性,提取该方法(某处)并将其传递给每个actor。函数是一等公民,你可以在构造函数中传递它们,避免重复自己。这是一个粗略的想法,您也可以尝试将其混合到trait
中。请查看:Scala Passing Function with Argument。