Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/google-sheets/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Akka 演员应该在哪一点';行为可以分裂_Akka - Fatal编程技术网

Akka 演员应该在哪一点';行为可以分裂

Akka 演员应该在哪一点';行为可以分裂,akka,Akka,我对阿克卡完全陌生。我很难理解什么时候应该将过去的类方法/行为拆分为akka消息。许多示例显示了作为一行println(“Howdy”)接收的消息 让我们假设我要执行以下操作: 给定一组预定义的正则表达式 从一本书中输入一系列句子。每条信息都是一个句子 对句子执行正则表达式 正则表达式的匹配项和非匹配项的增量计数 如果匹配,则执行HTTP post语句 akka专家在他们的头脑中使用了什么准则来打破这种局面?我会将这里的每个步骤作为单独的消息而不是几个方法调用吗?在我看来,我唯一会使用akka消

我对阿克卡完全陌生。我很难理解什么时候应该将过去的类方法/行为拆分为akka消息。许多示例显示了作为一行println(“Howdy”)接收的消息

  • 让我们假设我要执行以下操作:
  • 给定一组预定义的正则表达式
  • 从一本书中输入一系列句子。每条信息都是一个句子
  • 对句子执行正则表达式
  • 正则表达式的匹配项和非匹配项的增量计数
  • 如果匹配,则执行HTTP post语句

  • akka专家在他们的头脑中使用了什么准则来打破这种局面?我会将这里的每个步骤作为单独的消息而不是几个方法调用吗?在我看来,我唯一会使用akka消息的是#1(每条消息)和#6(阻止http调用)。这将使我对每一句话的处理都能完成相当多的工作(但不是阻塞工作)。这是否与我决定使用异步而不是不使用异步类似?对我来说,只有当我有机会执行阻塞操作时,才会执行此操作。

    我假设您希望在参与者中跟踪的状态是每个正则表达式的匹配数

    在这种情况下,如果没有太多正则表达式,那么初始方法是有效的。如果你有很多,每句话都经过每一个表达式,你将在演员线程上执行很多工作。这项工作在没有I/O的意义上是非阻塞的,但实际上它阻止了发送给此参与者的其他消息的进度,因此它在这个意义上是阻塞的。演员是单线程的,所以如果你有大量的输入句子,演员的邮箱将开始增长。如果你使用一个无限制的邮箱(这是默认的),你最终会去OOM

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

    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可能非常适合,因为它可以帮助确保您安全地处理对actor中状态的并发访问,并且它的容错机制将帮助您的应用程序在该状态损坏导致应用程序错误时恢复

    在您的例子中,一个或两个简单的计数器可以用Java的原子整数处理,因此我建议您使用一个基本类而不是actor。这将比使用演员简单得多。如果您想返回未来,可以使用Java8sCompletableFuture或Scala的concurrent.future,结果将比使用actor更简单

    综上所述,如果您确实希望使用一个参与者,那么设计可能不会保证多个参与者,因为您只有一个状态

    一般来说,参与者应该只承担一项责任——就像良好的面向对象设计一样。虽然您可以在单个参与者中接受消息,但您仍然可以决定将逻辑拆分为多个类。因此,您可以使用“RegexActor”,然后使用策略模式实现“MatchBehavior”,即在构建过程中传递RegexActor

    总而言之,我认为你不需要构建一堆参与者——参与者为你提供了事物之间的异步边界,但是你仍然可以从在参与者的行为中使用好的OO中获益。演员有一个信息——处理书中的台词——但它有一些行为可以在几个不同的类中组合。我将使用基本类来实现该行为,并在收到消息后让actor委托给其他类


    您希望事情变得简单—在使用actors时,会损失类型安全性和添加代码,因此我建议您确保使用它有一个很好的理由—存在于并发环境中的状态或分布。

    为什么每句工作是非阻塞的?感谢这一点—我的场景的目的是要有很多有许多句子(纯粹是为了尝试和演示一个问题,该问题具有非阻塞性工作,但每个参与者消息可能会有繁重的工作)。你给了我这个问题的方向。“println”演员的例子并不能很清楚地说明这一点