【问题标题】:Avoid concurrent execution of Akka actor避免同时执行 Akka actor
【发布时间】:2013-10-26 03:59:03
【问题描述】:

我目前每秒钟向 Akka Actor 发送一条消息,以便它执行任务。

如果当参与者收到新消息时该任务(函数)仍在运行,我希望参与者什么都不做。基本上,我希望演员函数仅在它尚未运行时才运行。

有什么好的方法可以做到这一点?我应该使用 Akka 演员还是以其他方式做?

干杯

【问题讨论】:

  • 如果函数在actor内部同步运行,它的行为就已经是这样了。它有一个消息框,一次只能处理一条消息。
  • @drexin 不完全是。这个问题似乎暗示如果演员很忙,应该删除该消息。 (但这对演员来说是一个糟糕的用例。演员不应该花费大量时间来处理消息。)
  • @Blackbird 如果actor已经在处理一些消息,你想防止干扰新的消息处理吗?或者您想在新消息到达时暂停/中止当前处理?
  • 我不希望当前的处理被中止。如果最后一条消息仍在处理中,我希望忽略该消息。 @RobinGreen 是对的。
  • 我是新手,但我想知道演员是否能够在完成处理消息后将演员邮箱的 MessageQueue 中的所有内容出列()。我相信这会产生您想要的效果,但如果执行需要几秒钟,消息可能会堆积起来。可能有架构上的原因,这是一个坏主意;这绝对是超出 Actor 预期范围的行为。

标签: scala akka actor


【解决方案1】:

Actor 一次处理一条消息。你描述的情况不可能发生。

【讨论】:

  • 但如果处理此类消息超过 1 秒,则可能会出现 OOME 邮箱溢出。
  • @SergiyPrydatchenko 除非您使用有界邮箱,不是吗?
  • @om-nom-nom 当然,如果您的应用程序可以阻止发件人线程阻塞,您当然可以使用有界邮箱。
  • 在发送新消息之前让处理器请求工作或确认已完成的工作
  • 如果我没记错的话,OP 只是他们的语言有点草率;其中...is received by the actor... 的意思是...is received by the mailbox of the actor...
【解决方案2】:

Akka actor 一个一个地异步处理他们的消息,因此您只能丢弃/忽略“过期”消息以避免额外的处理和由于 actor 的邮箱溢出而导致的 OutOfMemoryException-s。

您可以忽略 Actor 内部的过期(在您的情况下超过 1 秒)消息:

case class DoWork(createdTime: Long = System.currentTimeMillis)

final val messageTimeout = 1000L // one second

def receive = {
  case DoWork(createdTime) =>
    if((System.currentTimeMillis - createdTime) < messageTimeout) { doWork() }    
}

或者您可以创建一个自定义邮箱,该邮箱可以在内部丢弃过期邮件。

当然,正如 Robin Green 已经提到的,一般而言,actor 不应该在内部运行长时间运行的操作,因此这种方法仅适用于您的 actor 不需要处理其他类型的消息(它们不会及时处理)。如果 CPU 需求很高,您可以考虑将您的 Actor 移动到单独的调度程序上。

【讨论】:

  • 我不明白您所说的“过期”消息是什么意思,抱歉。
  • 如果你每秒向一个actor发送一条消息,并且如果你的actor从它的邮箱中收到一条消息,该消息在一秒前已经发送(创建)了,这意味着这条消息已经存储在邮箱超过一秒钟(当你的演员忙于处理前一个时) - 所以你可以安全地丢弃这条消息(如果它当然不包含重要数据)并等待下一条应该在第二。
  • @om-nom-nom 你是对的 - 对于远程参与者来说,直接从邮箱中删除额外的消息会更好(基于邮箱中的消息数量或它们的接收时间)。
猜你喜欢
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
  • 2023-04-02
  • 2018-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-27
相关资源
最近更新 更多