akka - Actor 的行为应该在什么时候 split

标签 akka

我对 Akka 完全陌生。我很难掌握何时应该将过去的类方法/行为拆分为 akka 消息。许多示例都将收到的消息显示为一行 - println("Howdy")。

  1. 假设我想要执行以下操作:
  2. 给定一组预定义的正则表达式
  3. 给定书中句子的输入流。每条消息都是一个句子。
  4. 对句子执行正则表达式
  5. 正则表达式匹配和不匹配的增量计数
  6. 如果匹配,则执行 HTTP post 语句。

akka 专家在头脑中使用什么准则来解决这个问题?我是否会将此处的每个步骤设为单独的消息而不是多个方法调用?在我看来,我唯一会使用 akka 消息的事情是 #1(每条消息)和 #6(阻止 http 调用)。这将使我对每个句子的处理实际上执行了大量的工作(但非阻塞工作)。这是否类似于我决定使用异步而不是不使用异步?对我来说,只有当我有机会进行阻塞操作时才会出现这种情况。

最佳答案

我假设您想要在 Actor 中跟踪的状态是每个正则表达式的匹配数。

在这种情况下,如果您没有大量正则表达式,您的初始方法是有效的。如果你有很多,并且每个句子都经过每个表情,那么你将在 Actor 线程上执行大量工作。从没有 I/O 的意义上来说,这项工作是非阻塞的,但它实际上阻止了发送到该 actor 的其他消息的进度,因此从这个意义上说它是阻塞的。 Actor 是单线程的,所以如果你有很多传入的句子,Actor 的邮箱就会开始增长。如果您使用无限制的邮箱(默认),您最终会出现 OOM。

一种解决方案是将正则表达式匹配到 Future。但是,您不能与该 future 共享参与者状态(即每个正则表达式的匹配计数),因为(在一般情况下)它将导致竞争条件。为了解决这个问题,您的 future 结果将向您的参与者发送另一条消息,其中包含需要更新的计数。

case class ProcessSentence(s: String)
case class ProcessParseResult(hits: mutable.Map[Regex,Int], s: String)
case class Publish(s: String)

class ParseActor {
  val regexHits = Map("\\s+".r -> 0, "foo*".r -> 0)
  def receive = {
    case ProcessSentence(s) => Future(parseSentence(s, regexHits.keys)).pipeTo(self)
    case ProcessParseResult(update, s) => 
      // update regexHits map
      if(update.values.sum > 0)
        self ! Publish(s)
    case Publish(s) => Future(/* send http request */)
  }

  def parseSentence(s: String, regexes: Seq[Regex]): Future[ProcessParseResult] = 
    Future{ /* match logic */}
}

关于akka - Actor 的行为应该在什么时候 split ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32319925/

相关文章:

java - java 类的隐式 jsonFormat

scala - 在 akka-http 中使用handleWebsocketMessage

scala - 为什么启用自动提交的 Kafka 客户端会在消费者关闭期间提交最新生成的消息的偏移量,即使该消息尚未被消费?

java - 尝试在我的 Play2 应用程序中利用 Akka future 和发挥 promise

scala - 使用 Akka 在一天中的固定时间安排任务

java - 如何测试 Actor Foo 向新创建的子 Actor Bar 发送消息?

scala - Akka:在Actor中一次处理一条消息的原因是什么?

java - 如何测试 akka actor 消息已发送给它的 child

scala - Akka Actor +玩!生成和捆绑 actor 实例的 2.0 Scala 版最佳实践

akka - 什么是 akka,它的用途是什么?