演员模型不是反模式吗,因为即发即弃的风格迫使演员记住状态?

Is the actor model not an anti-pattern, as the fire-and-forget style forces actors to remember a state?

在学习 Scala 时,我首先学到的东西之一就是每个函数 returns 东西。没有 "void"-function/method,例如 Java。因此,许多 Scala 函数是真正的函数,以数学的方式,并且对象可以在很大程度上保持无状态。

现在我了解到,actor 模型是 Scala 等函数式语言中非常流行的模型。但是,actor 提倡一种即发即弃的编程风格,调用者通常不希望被调用者直接回复消息(使用 "ask"/"?" 方法时除外)。因此,actors 需要记住某种状态。

我假设 actor 模型更像是可扩展性和可维护性(由于它的状态性)之间的权衡,有时甚至可以被视为反模式,我的假设是否正确?

Actor 是工具箱中专门用于处理和分发状态的工具。所以是的,他们应该有状态——如果他们没有,那么你就可以使用 Futures。

但是请注意,Actor(至少是 Akka Actors)处理 distribution(运行 在多个节点上位置透明),这两个 Futures 函数都无法做到. Actors 的并发方面是他们处理更复杂的情况——网络的结果。从这个意义上讲,Actor 通过使远程 case 成为 first-class 来统一远程 case 和本地 case。事实证明,如果您想要可靠、有弹性且快速的系统,那么网络消息传递正是您可以依靠和构建的东西。

希望这能回答您问题的 "big picture" 部分。

是的,您基本上是对的(当您说可扩展性与可维护性时,我不太确定您在想什么)。

由于 Akka,Actor 在 Scala 中很受欢迎(大概是因为它得到了 Lightbend 的支持而受到欢迎)。然而,Actor 在函数式编程世界中并不是普遍流行(尽管我想到的所有语言都有实现)。以下是我对其他两个 FP 语言社区的非常简化的印象(因此请对它们进行必要的调整),这两个社区使用 actor 的频率(远?)都低于 Scala。

  • Haskell 社区倾向于使用其中之一 STM/channels (often in an STM context). Straight up MVars 也经常出人意料地被使用。
  • Clojure 社区有时会吹捧自己内置的 STM 版本,但它的旗舰并发模型确实是 core.async,这又是它的核心渠道。

顺便说一句,STM、频道和演员都可以相互叠加;将它们作为相互排斥的方法进行比较有点奇怪。在实践中,虽然很少看到它们全部串联使用。

Actor 确实涉及状态(在 Akka 裙子类型安全的情况下),因此非常有表现力,几乎可以在并发方面做任何事情。通过这种方式,它们类似于副作用函数,后者比纯函数更具表现力。事实上,在某种程度上,Actor 是 OO 的纯粹本质,有其优点和缺点。

因此,Scala 社区的 sizable chunk 会说是的,如果大多数时候当您遇到并发问题时,您使用的是 actors,那可能是一种反模式。

  • 如果可以,请尝试仅使用 Futures 或 scalaz.concurrent.Tasks。 In return for less expressiveness you get more composability.
  • 如果您的问题自然地适用于单一的全局状态(例如,以您想要强制执行的全局不变量的形式),请考虑 STM。在 Scala 社区,虽然 an STM library exists, my impression is that STM is usually emulated by using actors.
  • 如果您的并发问题主要围绕流式传输多个数据源,请考虑使用 Scala 的 streaming libraries