Events 在事件驱动体系结构中,让所有服务将其事件发送到将其转发到适当服务的组件可以吗?

Events 在事件驱动体系结构中,让所有服务将其事件发送到将其转发到适当服务的组件可以吗?,events,service,architecture,event-handling,microservices,Events,Service,Architecture,Event Handling,Microservices,假设我想用服务A-D建立一个事件驱动的体系结构,其中事件传播如下 A / \ B C / D 换句话说, (1) A发布事件 (2) 订户B和C接收A的事件 (3) C发布事件 (4) 订户D接收的C事件 一种方法是让服务B和C直接侦听a向其中发送消息的队列。但我看到的问题是维护。一旦系统因1000个订阅变得复杂,就很难了解更新是如何传播的 我提出的解决方案是使用另一

假设我想用服务
A
-
D
建立一个事件驱动的体系结构,其中事件传播如下

            A
          /   \
         B     C
              /
             D
换句话说,

(1)
A
发布事件

(2) 订户
B
C
接收
A
的事件

(3)
C
发布事件

(4) 订户
D
接收的
C
事件

一种方法是让服务
B
C
直接侦听
a
向其中发送消息的队列。但我看到的问题是维护。一旦系统因1000个订阅变得复杂,就很难了解更新是如何传播的

我提出的解决方案是使用另一个服务
X
,它知道第一个图像中的树,并负责根据树指导事件的传播。每个服务都将其事件发布到
X
,并将事件发布到侦听服务。所以这有点像中间人

     A
     |
     X
    / \
   B   C
       |
       X
       |
       D
这也使得跟踪事件传播更加容易


这有什么坏处吗(除了与两倍的消息传输相关的额外成本)?

这是可以的,但是微服务不应该关心他们如何首先获得消息。从他们的角度来看,输入消息刚刚到达。然后,您会试图将系统设计为依赖于某些全局事件顺序,这在分布式可伸缩系统中是很难做到的。抵制这种诱惑,并将您的系统设计为仅依赖于事件的本地顺序(即事件源+DDD中聚合发出的事件流中的顺序)


我看到的一个缺点是可用性和可伸缩性可能会受到影响。然后,整个系统将出现单点故障。如果失败了,一切都会失败。当需要放大时,您将再次遇到问题,因为您将使用分布式消息传递系统。

您认为事件类似于在Winforms UI中实现的事件,发布者将事件直接发送给订阅者。EDA体系结构中的事件不是这样工作的。“事件”一词有了全新的含义

在我们开始之前,您正在将消息和事件的想法混杂在一起,而实际上它们需要分开。消息是对某个操作的请求,而事件是对某个操作已经发生的通知。本讨论的重要区别在于,消息发布者假定一个或多个其他进程将接收和处理该消息。如果消息未被某个对象处理,则会发生下游错误。事件没有这样的假设,可以不读而不会对任何事情产生不利影响。另一个区别是,一旦消息被处理,它们通常会被丢弃,而事件会被保留更长的时间(几天或几周)

考虑到这一点,您提到的“X”服务已经存在(请不要构建),并且是流程中不可或缺的一部分——它被称为总线。有两种类型的公共汽车;消息总线(比如RabbitMQ、MSMQ、ZeroMQ等)或事件总线(Kafka、Kinesis或Azure事件中心)。无论哪种情况,发布者都会将消息放到总线上,而订阅者则从总线上获取消息。您可以将总线服务器实现为多个物理总线,但想象一下,它们都是相同的逻辑总线

让您感到困惑的关键点是,这是一个微妙的区别,它认为消息总线具有指示消息去向的业务逻辑。谁获得什么消息的业务逻辑由订阅者决定——消息总线只是消息等待接收的一个等待位置

在您的示例中,A向总线发布消息类型为“MT1”的事件。B和C都告诉总线他们对“MT1”类型的事件感兴趣。当总线从B和C接收到关于“MT1”消息的通知请求时,总线为B创建一个队列,为C创建一个队列。当a发布消息时,总线将一个副本放入“B-MT1”队列,将一个副本放入“C-MT1”队列。注意,总线不知道为什么B和C想要接收这些消息,只是它们已经订阅了

这些消息在被各自的订阅者处理之前一直保存在那里(进程可以轮询或总线可以推送消息,但关键思想是消息在被处理之前一直保存)。一旦被处理,消息就会被丢弃

为了让C与D通信,D将订阅类型为“MT2”的消息,C将把它们发布到总线上

康斯坦丁在上面的回答中指出,这是一个单点故障,但可以使用标准网络体系结构(如故障切换服务器、本地消息持久性、消息确认等)来管理

你担心的一个问题是,有1000个订阅,很难遵循这条路,你是对的。这是EDA固有的缺点,您对此无能为力。最终的一致性也是企业将要抱怨的问题,但它是beast的一部分,从技术角度来看,它实际上是一件好事,因为它支持更大的可伸缩性。我发现使用“最终一致性”一词的最大问题是,企业认为它指的是小时或天,而不是秒

顺便说一句,整个讨论假设消息发布者和订阅者是不同的应用程序。所有相同的想法都可以应用于相同的地址空间,只需使用不同的总线即可。如果您是.net商店,请查看Mediatr。对于其他科技公司,我相信谷歌也知道类似的解决方案