什么样的设计决策会偏爱 Scala 的 Actors 而不是 JMS?

使用 Scala Actors 而不是 JMS 有什么区别?

例如,从性能和可伸缩性的角度来看,与 JMS 相比,Scala Actor 模型增加了什么?在哪些情况下使用 Actors 比使用 JMS 更有意义,即 Actors 解决了 JMS 无法解决的哪些问题?

13218 次浏览

JMS 和 Scala 参与者在理论上有相似之处,但并不认为它们必须在架构上解决相同的问题。角色应该是共享内存并发的轻量级替代品,因为在共享内存并发中,竞争和死锁通常很难意外创建。JMS 是一个复杂的 API,旨在跨越直接消息传递、发布/订阅、事务、 EJB 集成等。

最接近于参与者的 JMS 等价物是由非持久性、非事务性、非发布/订阅队列支持的消息驱动 bean。我称之为“简单的 JMS bean”。

现在,回到你的问题。

性能是一个很难讨论的问题,因为 JMS 是一个规范而不是一个实现。在使用简单的 JMS bean 时,我希望性能与参与者在时间和内存方面大致相似,并且可能有一点优势。当您向 JMS 添加功能(比如 pub/sub、事务等)时,性能自然会进一步下降,但随后您将尝试比较苹果和橙子。

至于可伸缩性,简单的 JMS bean 的伸缩方式应该与角色几乎完全相同。将事务添加到 JMS 组合中自然会损害可伸缩性,具体程度取决于事务的范围。

更广泛的问题是,参与者做什么是 JMS 不能做的。好吧,如果没有内置的酒吧订阅或交易,似乎参与者会从 JMS 中减去——大体上这是真的。但问题是: 参与者只需要很少的代码,因此我可以很高兴地将它们用于非常细粒度的并发。在普通的 Java 代码中,我可能会说: “我不想干扰 JMS 及其依赖项或者它所需要的代码等等,所以我只需要生成一个线程,使用一个锁,并共享一个数据结构。”对于 Scala 演员,我更倾向于说: “我只需要创建一个演员,然后继续前进。”

在设计上也有一个哲学上的区别。参与者有一个简单的、内置的主管层次结构概念。演员通常被用在一个“让它崩溃”的设计。如果一个演员因为某种原因死亡,那么另一个演员负责决定如何处理这个问题,比如重新启动那个演员,杀死一群演员并重新启动所有的演员,或者杀死一群演员和自己,以便其他演员可以处理这个问题。这类东西可以附加到 JMS 上,但它不是 API 的核心,必须以某种方式从外部进行管理。

顺便说一下,有关更深入 JMS 所涵盖领域的 Scala 角色库,请参见 阿卡。Akka 还为许多常见的角色层次结构策略带来了声明性方法。