事件驱动架构入门
主要参考资料:
软件架构-事件驱动架构: https://blog.csdn.net/liuxinghao/article/details/113923639
目录
- 简介
- 事件队列
- 事件日志
- 事件收集器
- 响应队列
- 读事件 vs. 写事件
简介
事件驱动架构是一种系统或组件之间通过发送事件和响应事件彼此交互的架构风格。当某个事件发生时,组件A不直接调用组件B,而只是发出一个事件。组件A不知道哪些组件监听并处理这些事件。事件驱动架构可以在进程内和进程间使用。比如,GUI框架中会大量使用事件驱动。
事件队列
在事件驱动架构中,你会有一个或多个集中的事件队列,所有的事件被处理前,会先保存在集中的事件队列中。下面给出一个简单示例:
事件插入队列时是有序的,这样就可以顺序处理这些事件。
事件日志
写入事件队列时,消息可能写入到事件日志(通常是磁盘存储)中。如果发生系统崩溃,系统只需要重放事件日志即可恢复到崩溃前的状态。下面是一个事件驱动架构的示例,其中包括一个用于持久化事件的事件日志:
我们还可以通过备份事件日志,来备份系统状态。在将新版本的系统部署在生产环境之前,可以使用这个备份数据对其性能进行测试。或者,通过重放事件日志的备份,来重现某些错误。
事件收集器
请求都是通过网络传输,比如HTTP或者其他协议。为了保持一致,可以通过事件采集器接收来自不同来源的事件。下面是一个添加了事件收集器的事件驱动架构示例:
响应队列
有时,我们还需要向请求(即事件)返回响应,所以,很多事件驱动架构除了包含事件队列,还会有一个响应队列。下面是包含事件队列(入队队列)和响应队列(出队队列)的事件驱动架构示例:
如你所见,响应队列必须路由到正确的事件收集器。比如,如果HTTP收集器(本质上是web服务器)通过HTTP接收的请求发送到事件队列中,则该事件生成的响应可能也需要通过HTTP收集器发回客户端。
通常,响应队列不会持久化,也就意味着它不会写入事件日志,只有输入的事件才会持久化到事件日志中。
读事件 vs. 写事件
如果将所有传入的请求都认为是事件,就需要将这些事件都推送到事件队列中。如果事件队列是实现了持久化(持久化到事件日志中),就意味着所有事件都需要持久化。通常持久化都比较慢,如果我们能够过滤掉一些不需要持久化的事件,我们就能够提升队列的性能。
我们将事件持久化到事件日志的原因是,我们可以重放事件日志,并重建因为事件引起的系统状态变化。为了支持这个特性,实际上只需要持久化更改系统状态的事件。换句话说,我们只需要将事件分为读事件和写事件。读事件只读取系统数据,不会更改,写事件会更改系统数据。
通过根据读和写划分事件,我们只需要持久化写事件的消息即可。这将提升事件队列的性能,提升比例大小,取决于读写事件之间的比例。
为了将事件划分为读写事件,需要在事件到达事件队列之前,也就是事件收集器中进行区分。否则,事件队列无法知道到达的事件是否需要持久化。
还可以将事件队列拆分为两个,一个用于存储读事件的事件队列,一个用于存储写事件的事件队列。这样读事件就不会慢于写事件,事件队列也不需要检查每条事件是否需要持久化。读事件队列不需要进行持久化,写事件队列始终持久化事件。
下面是一个事件驱动架构的示例,其中事件队列分为读和写事件队列:
上图示例中箭头比较乱,但实际上创建3个队列并在它们之间分发消息简单很多。