0

我一直在阅读一些东西,发现了一些真正让我的想法混乱的库,比如 Akka、Quasar、Reactor 和 Disruptor,Akka 和 Quasar 实现了 Actor 模式,而 Disruptor 是一个线程间消息传递库,而 Reactor 是基于. 那么与简单的方法调用相比,使用消息驱动架构的优势和用例是什么?

给定一个 RabbitMQ 队列侦听器,我从该方法接收一条消息,决定 RabbitMQ 消息是哪个 Type ( NewOrder, Payment,...)。

使用消息驱动库,我可以做到。

伪代码:

actor.tell('decider-mailbox',message)

基本上是说“我把这个消息放在这里,当你们可以处理它时,做它”)等等,直到它被保存。并且actor再次准备好接收另一条消息

但是像这样直接调用方法messageHandler.handle(message),不是更好,更不抽象吗?

4

3 回答 3

3

Actors 模型看起来很像人们一起工作。它基于消息传递,但还有更多内容,我想说并非所有消息传递模型都是相同的,例如Quasar实际上不仅支持类似 Erlang 的演员,还支持更简单的类似 Go 的通道但不提供容错模型(顺便说一句,纤维就像线程一样,但更轻量级,即使完全没有任何消息传递也可以使用)。

方法/函数遵循严格的、可嵌套的调用-返回(即请求-响应)规则,通常不涉及任何并发性(至少在命令式和非纯函数式语言中)。

相反,从广义上讲,消息传递允许更松散的耦合,因为它不强制执行请求-响应规则并允许通信方同时执行,这也有助于隔离故障、热升级和一般维护(例如,Actor模型提供这些功能)。通常,消息传递还可以通过对消息使用更动态的类型来允许更松散的数据契约(这对于 Actors 模型尤其如此,其中每一方或Actor都有一个传入通道,即他的邮箱)。除此之外,细节很大程度上取决于您正在考虑的消息传递模型/解决方案,例如通信渠道可以同步交互部分或具有有限/无限缓冲,允许多个源和/或多个生产者和消费者等。

请注意,RPC实际上是消息传递,但具有严格的请求-响应通信规则。

这意味着,根据情况,其中一个可能更适合您:当您处于调用返回规则和/或您只是使您的顺序代码更加模块化时,方法/函数会更好。当您需要一个潜在并发的、自治的“代理”网络进行通信但不一定在请求-响应规则中时,消息传递会更好。

至于演员模型,我认为你可以通过阅读这篇博文的第一部分来建立更多的见解(注意:我是这篇文章的主要作者,我是平行宇宙和类星体的一部分 -开发团队):

演员模型是一种容错和高度可扩展系统的设计模式。Actor 是独立的工作模块,仅通过消息传递与其他 Actor 进行通信,可以与其他 Actor 隔离失败,但可以监视其他 Actor 的故障并在发生这种情况时采取一些恢复措施。Actor 是简单、孤立但协调的并发工作者。

基于 Actor 的设计带来了很多好处:

  • 自适应行为:仅通过消息队列进行交互使参与者松散耦合并允许他们:
    • 隔离故障:邮箱正在解耦消息队列,允许参与者重新启动而不会中断服务。
    • 管理进化:它们可以在不中断服务的情况下更换演员。
    • 调节并发:经常接收消息并丢弃溢出,或者增加邮箱大小可以最大化并发,但分别以可靠性或内存使用为代价。
    • 调节负载:减少接听电话的频率和使用小邮箱会降低并发性并增加延迟,通过参与者系统的边界施加背压。
  • 最大并发容量
    • Actors 在内存消耗和管理开销方面都非常轻量级,因此在一个盒子中甚至可以生成数百万个 Actor。
    • 因为actor不共享状态,它们可以安全地并行运行。
  • 低复杂度
    • 每个参与者都可以通过改变其私有状态来实现有状态行为,而不必担心并发修改。
    • 参与者可以通过有选择地以逻辑而不是到达顺序从邮箱接收消息来简化他们的状态转换逻辑。
于 2015-09-18T06:49:36.077 回答
1

不同之处在于处理发生在不同的线程中,因此当前线程已准备好接收并转发下一条消息。当您从当前线程调用处理程序时,它会被阻塞,直到处理完成。

于 2015-09-04T07:13:28.130 回答
1

在某种程度上,这只是定义抽象的问题。有人说最初的面向对象编程实际上应该基于消息传递,并且在对象上调用方法将具有向其发送消息的语义(具有与参与者类似的异步非阻塞行为)。

我们在最流行的语言中实现 OO 的方式就是它变成了今天的样子——对象的“同步阻塞顺序”,从与调用者相同的执行上下文(线程/进程)控制和运行。这很好,因为它很容易理解,但是在设计并发系统时它有其局限性。

理论上,您可以创建一种语法与 Java 相似的语言,但赋予它不同的语义——使object.method(arg)实际上在内部类似于actor.tell(msg)。有很多习惯用法试图在简单的方法调用后面隐藏异步调用和消息传递,但一如既往地取决于用例。

Akka 提供了一种很好的新语法,它清楚地表明我们正在做的事情与在对象上调用方法完全不同,部分原因是为了减少混淆并使消息传递更加明确。最后,您说的是同一件事 - 您正在向系统中的参与者发送消息,但与直接调用其中一个方法相比,您这样做的约束更少。

于 2015-09-06T10:41:48.033 回答