事件驱动架构图解——生产、发布、消费

事件驱动架构的工作原理,在一张交互式画布上讲清楚:生产者、事件总线、订阅者与事件存储,以及解耦如何让新消费者不必改动生产者就能接入。

事件驱动架构靠事件让系统之间通信,从而实现解耦:生产者发布已经发生的事,总线把它路由给订阅者,事件存储则保留这段历史。

事件驱动架构图解——生产、发布、消费

The interactive FlowJam canvas for this explanation — every lane, row and arrow above is a real QueryChart diagram you can open and edit.

How to read this visual

  • 从左往右读:发出,发布,消费与留存。
  • 生产者那一行从不直接指向某个消费者——每一支箭头都要穿过总线,这就是被画出来的解耦。
  • 下面那条分支是事件存储:被实时消费的那些事件,同时也被留存下来,供重放和审计使用。

产出与发布

“服务产出领域事件”就是生产者的全部职责——记录某件事发生了。“事件被发布到总线上”和“总线把事件路由给订阅者”是发布这一步:总线接收事件,并投递给每一个订阅过它的一方。发出那个方框上的注释把规则说得很明白——生产者并不知道谁在监听,而这正是这套系统可扩展的原因。

实时消费

“消费者异步处理事件”是右侧那条路径:订阅者按自己的节奏对每个事件做出反应——更新一个读模型、发一封邮件、触发一条工作流。正因为是异步处理,慢的消费者才不会拖慢生产者,图上也才把两者放在不同的条带里。

留存历史

“事件存储保留完整历史”按顺序记下每一个事件,而“事件可以重放,用于审计或恢复”说明了这份记录是干什么用的——重建一个状态、回答一个审计问题,或者用过去的事件喂给一个新的消费者。“新消费者接入,不必改动生产者”是这套架构的试金石:因为历史在那里,总线又按订阅路由,加一个服务不会改动上游的任何东西。

Key relationships and takeaways

  • 事件记录的是已经发生的事;它不是给某个特定对象的命令。
  • 总线把生产者和消费者解耦——双方都不知道对方的身份和节奏。
  • 事件存储让这段历史成为可以重放的权威记录。
  • 消费者是异步的:慢的消费者永远不会阻塞生产者。
  • 新消费者靠订阅接入——这套架构关于灵活性的全部主张都建立在这一点上。

When to use this visual

  • 向一个正从请求/响应转向事件的团队,讲清楚生产者、总线与消费者这套划分。
  • 设计一次新的集成:事件存储能回答历史是需要保留,还是消费完即弃。
  • 审视一套已有的事件驱动系统,找出那个经典的失败——一个名义上的消费者,实际上是同步依赖。

运作方式

  1. 把各方改成你自己的系统

    把生产者、消费者和事件名换成你真实的服务以及它们发布的事件,再补上这张通用图没覆盖到的。

  2. 写出主题名和它们的消费者

    在总线上的每个事件旁标注主题名以及谁订阅了它,让解耦成为一张记录在案的地图,而不是一句断言。

  3. 补上故障分支

    插入总线宕机、消费者处理到一半挂掉、同一个事件到达两次时会发生什么——每一条都配上处理它的幂等或重试机制。

  4. 扩展事件存储

    把你系统实际采用的留存与重放规则加进去——历史保留多久、哪些状态由它重建——让这条存储带反映你的策略。

常见问题

什么是事件驱动架构?

它是一种架构风格:组件之间通过发布和订阅事件来通信,而不是互相直接调用。一个创建或改变了什么的服务,会发布一个描述已发生之事的事件;总线把它路由给每一个关心它的订阅者;事件存储则保留这段历史。因为生产者从不点名自己的消费者,系统可以在不触碰已有部分的情况下继续生长。

命令和事件有什么区别?

命令是发给某个特定接收方的指令——“处理这个订单”——并且期待一个结果。事件则是一条记录,说明某件事已经发生——“订单已下单”——它不点名任何接收方。这个区分之所以重要,是因为命令把发送方耦合到接收方,而事件让接收方可以自由变化。图上的生产者只发出事件,这正是让总线保持松耦合的原因。

事件存储是干什么用的?

事件存储是系统留存下来的历史:每一个事件,按顺序,永久保留。它有三个用途——审计(什么时候发生了什么)、恢复(通过重放事件重建一个服务的状态),以及可扩展性(新的消费者可以读过去的事件来追平)。图上把它画成下面那条分支,因为它是对同一批事件的另一种用法,而消费者是实时处理这些事件的。

事件驱动架构有哪些故障模式?

经典的几种是:事件被重复投递(所以消费者必须幂等)、事件被乱序处理(所以消费者必须处理顺序问题),以及死信队列(反复失败的事件)。图上那种异步处理正是让这些变得可控的原因——消费者可以重试而不阻塞生产者——这也是为什么操作步骤里的故障分支是这套设计务实的另一半。

在 QueryChart(FlowJam)中编辑这张图解

把上面这张事件驱动画布原样打开成你自己的图表,把生产者和消费者改成你的服务,画出你自己的事件。

在 QueryChart(FlowJam)中编辑这张图解

可视化图解中的更多内容