Scala如何使用akka actor有效地处理超时操作
Posted
技术标签:
【中文标题】Scala如何使用akka actor有效地处理超时操作【英文标题】:Scala how to use akka actors to handle a timing out operation efficiently 【发布时间】:2013-07-11 11:46:53 【问题描述】:我目前正在使用 Rhino 在一个安静的服务中评估 javascript 脚本。我希望有一个评估超时。 我创建了一个模拟示例演员(使用 scala 2.10 akka 演员)。
case class Evaluate(expression: String)
class RhinoActor extends Actor
override def preStart() = println("Start context'"); super.preStart()
def receive =
case Evaluate(expression) ⇒
Thread.sleep(100)
sender ! "complete"
override def postStop() = println("Stop context'"); super.postStop()
现在我运行如下使用这个actor:
def run
val t = System.currentTimeMillis()
val system = ActorSystem("MySystem")
val actor = system.actorOf(Props[RhinoActor])
implicit val timeout = Timeout(50 milliseconds)
val future = (actor ? Evaluate("10 + 50")).mapTo[String]
val result = Try(Await.result(future, Duration.Inf))
println(System.currentTimeMillis() - t)
println(result)
actor ! PoisonPill
system.shutdown()
在这样一个可能同时有请求的闭包中使用 ActorSystem 是否明智?
我应该将 ActorSystem 设为全局吗,在这种情况下可以吗?
有没有更合适的替代方法?
编辑:我认为我需要直接使用期货,但我需要 preStart 和 postStop。目前正在调查。 编辑:似乎你没有得到期货的那些钩子。
【问题讨论】:
【参考方案1】:我会尽力为您解答一些问题。
首先,ActorSystem
是一个非常重的构造。您不应该为需要参与者的每个请求创建一个。您应该全局创建一个,然后使用该单个实例来生成您的演员(在run
中您将不再需要system.shutdown()
)。我相信这涵盖了您的前两个问题。
您在这里使用演员执行 javascript 的方法对我来说似乎是合理的。但是,您可能希望在Router
后面汇集一堆RhinoActor
s,而不是每个请求都启动一个actor,每个实例都有自己的rhino 引擎,该引擎将在preStart
期间设置。这样做将消除每个请求的犀牛初始化成本,加快你的 js 评估。只要确保你的游泳池大小合适。此外,如果您采用这种方法,则无需为每个请求发送 PoisonPill
消息。
您可能还想查看非阻塞回调 onComplete
、onSuccess
和 onFailure
,而不是使用阻塞 Await
。这些回调也尊重超时,并且比阻塞更高的吞吐量更可取。只要上游等待此响应的任何方式都可以处理异步性(即支持异步的 Web 请求),那么我建议走这条路线。
最后要记住的是,即使代码会在超时后返回给调用者,如果参与者尚未响应,参与者仍会继续处理该消息(执行评估)。它不会仅仅因为呼叫者超时而停止并转到下一条消息。只是想澄清一下,以防万一。
编辑
针对您关于停止长时间执行的评论,有一些与 Akka 相关的事情需要首先考虑。您可以调用停止actor,发送Kill
或PosionPill
,但如果处理当前正在处理的消息,这些都不会停止。他们只是阻止它接收新消息。在您的情况下,对于 Rhino,如果无限脚本执行是可能的,那么我建议在 Rhino 本身内处理这个问题。我会深入研究这篇文章 (Stopping the Rhino Engine in middle of execution) 上的答案,并在 Actor 中设置您的 Rhino 引擎,使其在执行时间过长时会自行停止。该失败将踢出到主管(如果被池化)并导致该池化实例重新启动,这将在preStart
中启动一个新的 Rhino。这可能是处理长时间运行脚本可能性的最佳方法。
【讨论】:
谢谢,这很有帮助。什么是迫使演员停止的最佳方式,因为我不希望我的线程建立处理潜在的无限脚本? @JPullar,围绕您的评论在我的回答中添加了更多信息以上是关于Scala如何使用akka actor有效地处理超时操作的主要内容,如果未能解决你的问题,请参考以下文章