“消息传递”系统与“基于事件”系统的优点


27

我的问题来自一个没有受过教育的观点。

消息传递 ”系统与“ 基于事件 ”系统的相对优点是什么?

为什么一个选择另一个?他们的优缺点是什么?

我不仅想知道“理论上”,而且想知道“实践中”。

编辑:

具体问题

我想构建可充当小型服务(每个执行一些小任务或提供一些信息)的可插入组件的系统。

服务可以:

  • 分层,以便一项服务的输出可以充当另一项服务的输入之一
  • 具有包含层次结构,因此一个服务可以由另一服务包含,而无需前面句子中提到的特定输入/输出关系

该系统的目标是将另一个系统中的单个低级事件流转换为更高级别的信息和功能,并另外提供一个返回到另一个提供单个事件系列的系统的通道。

如果还不够,我可以提供更多详细信息。

环顾四周后。可能更好地描述我的情况。

看来这很适合我的情况:http : //akka.io/


3
您需要提供一些上下文。基于事件的系统通常是通过消息传递模型建立的,而魔鬼在细节中。例如,在C#中,消息传递模型允许执行在不同的线程上进行,而在调用线程上触发事件。
Telastyn

1
我可以根据我的项目的具体情况提出问题,但是我想使其更加通用,以使其不仅适用于我。
sylvanaar 2012年

1
正如@Telastyn所说-“消息传递”和“基于事件”不是互斥的。
2012年

尽管描述为基于事件的语义和描述为消息传递的语义之间存在趋势,但它们的行为将特定于任何给定的系统。您只需查看消息传递系统概述中给出的选项数量,即可看到简单事件和某些消息之间几乎没有什么区别,但是其他消息的语义可能完全不同。您需要告诉我们您要解决的问题
Mark Booth

Answers:


17

以我的经验,唯一的区别是在大多数邮件传递系统中,邮件的发件人知道(并且经常声明)邮件的收件人。

因此,发件人定义了预期收件人或逻辑收件人组的某些ID,而不是引发事件并使任何受该事件约束的人都将其获取,然后直接将消息发送给他们,或者通过消息代理(尽管可以将OS视为基于事件的系统中的消息代理)。

显然,Telastyn在C#的事件实现中提到了线程化的情况,但是您仍然可以创建自己的在不同线程上执行的pub / sub模型。


21

这是苹果和橘子:

事件引发时,事件驱动系统可以对作为消息传递的事件做出反应(在这种情况下,消息是隐含的不可变的非共享数据)。这是一个纯粹的建筑设计。

消息传递系统可以创建和传递消息的事件驱动。这是一个纯粹的实现设计。

两者不是互斥的。

示例:您可以用任何语言来实现事件驱动的设计,这也可以是Erlang中的消息传递环境。


11

“消息传递”和“基于事件”之间的大部分困惑与体系结构和实现细节有关。我已经看到(并编写了)事件驱动的系统,这些系统实际上使用OS为实现提供了消息。我猜您真的是在指建筑构想。

正如许多人已经指出的那样,“消息传递”和“基于事件”并不是真正避免混淆的好词。

“消息传递”系统与“基于事件”系统的相对优点是什么?

讯息传递

首先,我要猜测一下,当您说一个“消息传递”系统时,您所谈论的是一个对象将消息传递给另一个特定对象的系统。当我想到基于这种范式的系统时,我通常会想到一种系统,其中检测到某事物的对象知道需要告知某人的信息。(我没有指定它如何知道,只是它知道。)

这种类型的体系结构对于生产者和消费者众所周知的系统非常有用。消息的产生者知道谁必须接收消息,或者消费者必须知道从谁那里得到消息。

如果您正在编写银行业务应用程序,那么您会希望您真的想知道将交易发送给谁以及交易来自谁。

基于事件

我相信您在考虑的另一种系统是,当您说“基于事件”的系统时,一个对象会引发“事件”而不知道谁(如果有人)会做出响应。

这种类型的事件驱动的体系结构非常适合生产者不关心谁消费事件或消费者根本不关心谁生产事件的系统。

通常,在您不知道消费者与生产者之间的关系以及期望这种关系是动态的情况下,这些系统非常有用。

我在其中使用过的一个系统是该应用程序实际上由在运行时加载的动态配置的模块(插件)组成的系统。加载模块后,它将注册它关心的事件。结果是一个非常容易扩展功能的系统。

例如,假设条件A引发了事件EA,该事件通常导致响应RA。导致响应RA的对象只是注册接收事件EA,并在事件到达时对其采取了措施。现在,假设我们要向EA添加一个新的响应,称为RA_1。为此,我们只需添加一个寻找EA并生成响应RA_1的新对象。

以下是一些示例(使用您的术语):

  • “消息传递”:您的老板告诉您填写时间表。
  • “事件驱动”:部门秘书向所有人发送电子邮件,提醒他们他们的时间表是今天。

4
这让我想起了...这是月末,所以我最好把时间表做好。
戴夫·奈

2

在SOA中,您具有命令消息和事件消息的概念。两者都需要。

但是,命令消息与接收者端点之间的行为耦合较高,因为它明确要求端点执行某些功能。它不必绑定到特定端点(可以在运行时配置或确定)。

另一方面,事件消息在发送者/接收者之间没有行为耦合,因为发送者不知道接收者将如何处理消息。它甚至不知道是否有人订阅了该事件。

有关更多背景知识,欢迎您细读我的服务总线网站:http : //www.servicebus.co.za


1

以我的经验,两者之间最大的区别是消息传递系统中的消息是一流的对象,而事件驱动系统中的事件则简单得多。消息倾向于携带信息,并且信息可以被转换,存储,检索和重新发送。事件倾向于携带更小,更集中的信息位,这些信息会立即被消耗然后丢弃。它们往往是从事件源直接发送到一个或多个事件接收器的,而消息通常是在几个接收者之间路由的,并且可以在沿该路由的任何点进行转换/翻译/包装或以其他方式处理。他们使用类似的技术(总线,队列,过滤器等),但它们实际上是完全不同的野兽。


0

从实际的角度来看,消息通常被实现为一个内存块,该内存块从发送者的地址空间复制到接收者的地址空间(或者被强制为不可变对象),因此您可以立即获得线程安全。

在某些情况下,消息传递必须由发送者指定接收者,但在其他情况下,您可以将消息发布到邮箱中,任何人都可以侦听该邮箱中的消息,因此在紧密耦合方面具有一定的灵活性。当然,您可以拥有一个邮箱,合同中的约定为“ 发生此事件时,我将向该邮箱发布消息”。

对于事件,您正在向事件的所有者注册委托或回调。在面向对象的编程中,这意味着事件所有者保留对注册以接收事件的对象的引用。有时这可能导致簿记噩梦,试图找出哪些对象忘记注销其事件处理程序。这意味着,直到目标所有者不再做任何有用的事情为止,都无法对目标进行垃圾回收,直到事件所有者被垃圾回收为止。

就个人而言,我会选择通过事件传递消息,除非在事件强制您执行的情况下(例如Windows GUI编程等)。


就是说,我通过存储weak_ptr并在每次调用事件时从侦听器集中清除所有.expired()指针,解决了C ++事件系统中的循环问题(您的簿记噩梦)。事件对象不拥有接收者对象,并且这些指针语义清楚地表明了这一点。
罗宾逊
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.