事件驱动架构(EDA)
https://mp.weixin.qq.com/s/nA8XFD2Rx_7qA_LxltGGHw

https://mp.weixin.qq.com/s/cD3auglgKzObUnRfau3t7A

解析事件总线的4种实现方式

互联网架构师 2017-08-12
 
作者|Mustafa Turan译者|薛命灯架构师 Mustafa Turan 在 Hackernoon 上分享了事件总线的几种实现方式,并总结了每一种实现方式的优缺点。

基于事件驱动的分布式异步架构模式多用于构建高可伸缩的反应式应用程序,适用于各种从简单到复杂的应用场景。它的核心思想是去耦合,将消息的发送和接收分开,实现异步处理消息事件。

事件总线是实现基于事件驱动模式的方式之一,或者可以将其称为“Broker Topology”。事件发送者将事件消息发送到一个中心 broker 上,事件订阅者向中心 broker 订阅和接收事件,然后再处理接收到的事件。当然,订阅者不仅可以接收和消费事件,它们本身也可以创建事件,并将它们发送到事件总线上。下面列出了 4 种事件总线的实现方式,并对它们的优缺点进行了总结。

事件总线和多个订阅者(绿色箭头)和通知发送者(红色箭头)

四种实现方式向所有的订阅者发送事件

事件总线直接将输入事件(红色箭头)发送给订阅者(蓝色方块)

参与者

  • 事件总线

  • 订阅者(事件处理器)

  • 事件创建者

实现

事件创建者向事件总线发送事件,事件总线将收到的事件发送给所有的订阅者。订阅者既可以处理接收到的事件,也可以创建新事件,然后把它们发送给事件总线。事件总线不关心订阅者是否成功接收到消息。

功能需求

  • 通知

  • 订阅

  • 退订

优势

实现起来很简单。

不足

事件总线需要将每一个事件消息复制一份给订阅者,也就是说,如果有 1000 个订阅者,每一个事件都会有 1000 份拷贝,这样会占用大量的内存。

事件总线不保证消息传递的可靠性,它会尝试给订阅者发送消息,而且只会尝试一次,如果出现错误,比如网络连接错误,订阅者可能就会收不到消息。另外,事件总线不负责过滤消息,所以订阅者需要自己实现过滤逻辑。

Elixir 的参考实现:

https://github.com/mustafaturan/event_bus/commit/08a955294c1d1c5bec2c7fef28ed255400e5f322

向所有订阅者发送事件影子

事件总线和事件存储及事件观察者

参与者

  • 事件总线

  • 事件创建者

  • 订阅者

  • 事件存储(Event Store)

  • 事件观察者(Event Watcher)

 实现

事件总线在收到事件创建者发送过来的事件后,把事件保存到事件存储里,然后将事件影子(Event Shadow,也就是对原始事件的引用)发送给所有的订阅者。订阅者根据事件影子从事件存储里获取事件数据,再对数据进行处理。

事件总线为每一个事件创建一个事件观察者,观察者持有订阅者列表,当所有的订阅者都接收到消息后,观察者负责把事件从事件存储里删除。

事件总线仍然不保证订阅者一定会收到所有事件影子。如果有订阅者接收消息失败,相应的观察者就会被标记为“skipped”。

 功能需求

  • 通知

  • 订阅

  • 退订

  • 保存 / 删除 / 获取

  • 标记完成 / 跳过

 优势

因为事件消息被保存在事件存储里,发送给订阅者的只是事件引用,所以占用内存会小很多。

 不足

订阅者需要调用额外的方法,比如在收到事件影子之后要调用方法去获取事件数据,在处理完事件后还要调用方法通知事件总线已完成处理,或者通知事件总线跳过某个事件。

另外,在事件总线端还要实现事件存储和事件观察者。这个对事件存储的实现要求比较高,如果订阅者数量很多,事件存储的读负载会很重,而且在写入事件时是阻塞式的。

这种实现方式仍然不会为订阅者过滤事件,所以订阅者还是需要自己实现事件过滤。

Elixir 的参考实现:

https://github.com/mustafaturan/event_bus/releases/tag/v0.2.1

向经过过滤的订阅者发送事件影子

第三种实现方式与第二种是一样的,只不过不是将事件影子发送给所有订阅者,而是发送给经过过滤的订阅者,也就是说 只发送给其中的一部分订阅者。事件总线需要记录订阅者感兴趣的主题,在这里可以使用正则过滤器为订阅者过滤主题。

这种方式的优势与不足和第二种也是一样的,只是多了事件过滤功能。

Elixir 的参考实现:

https://github.com/mustafaturan/event_bus

按顺序传递

为了保证顺序传递,可以对事件进行分区。关于如何通过分区来保证顺序传递,可以参考 Kafka 的论文,基本原理是让消费者消费属于自己的分区。

不足

动态增加分区或减少分区会变得很困难,而且需要自己实现分区器,消费者的实现也很复杂。

在实现订阅者时要注意的一些问题

对于第一种和第二种方式,需要通过阻塞的方式进行事件类型(也就是主题)匹配,避免进行不必要的事件拷贝,浪费了内存。

对于第三种和第四种方式,需要通过非阻塞的方式进行事件类型(也就是主题)匹配,因为订阅者只接收感兴趣的事件。

阅读原文

https://hackernoon.com/event-bus-implementation-s-d2854a9fafd5

中央事件总线 事件驱动架构(EDA) 解析事件总线的4种实现方式的更多相关文章

  1. 后端开发实践系列之三——事件驱动架构(EDA)编码实践

    在本系列的前两篇文章中,笔者分别讲到了后端项目的代码模板和DDD编码实践,在本文中,我将继续以编码实践的方式分享如何落地事件驱动架构. 单纯地讲事件驱动架构(Event Driven Architec ...

  2. IDDD 实现领域驱动设计-CQRS(命令查询职责分离)和 EDA(事件驱动架构)

    上一篇:<IDDD 实现领域驱动设计-SOA.REST 和六边形架构> 阅读目录: CQRS-命令查询职责分离 EDA-事件驱动架构 Domin Event-领域事件 Long-Runni ...

  3. CQRS(命令查询职责分离)和 EDA(事件驱动架构)

    转载CQRS(命令查询职责分离)和 EDA(事件驱动架构) 上一篇:<IDDD 实现领域驱动设计-SOA.REST 和六边形架构> 阅读目录: CQRS-命令查询职责分离 EDA-事件驱动 ...

  4. 事件驱动架构 (Event-Driven Architecture,EDA) 简介

    EDA 是一种侧重于以生成/消费为基础的异步通信的架构模式.这主要对照于传统的基于线程的同步系统. EDA 是一种以事件 (event)为核心,提供事件产生,路由,消费已经结果回调等机制的架构模式. ...

  5. EDA: Event-Driven Architecture事件驱动架构

    EDA: Event-Driven Architecture事件驱动架构 2009-09-24 17:28 5 赞  异步编程      软件架构      EDA事件驱动        SOA的核心 ...

  6. ENode 1.0 - 事件驱动架构(EDA)思想的在框架中如何体现

    开源地址:https://github.com/tangxuehua/enode 上一篇文章,我给大家分享了我的一个基于DDD以及EDA架构的框架enode,但是只是介绍了一个大概.接下来我准备用很多 ...

  7. enode框架step by step之事件驱动架构(EDA)思想的在框架中如何体现

    enode框架step by step之事件驱动架构(EDA)思想的在框架中如何体现 上一篇文章,我给大家分享了我的一个基于DDD以及EDA架构的框架enode,但是只是介绍了一个大概.接下来我准备用 ...

  8. Netty源码解析 -- 事件循环机制实现原理

    本文主要分享Netty中事件循环机制的实现. 源码分析基于Netty 4.1 EventLoop 前面分享服务端和客户端启动过程的文章中说过,Netty通过事件循环机制(EventLoop)处理IO事 ...

  9. 【第三篇】学习 android 事件总线androidEventbus之list数据事件的传递,发送list数据事件到另外一个Activity

    这个和普通的事件总线的发送接收一样. package com.example.mysimpleeventbus; import java.util.ArrayList; import java.uti ...

随机推荐

  1. 解决[BScroll warn]: Can not resolve the wrapper DOM. Vue better-scroll

    在开发项目过程中,使用better-scroll插件中遇到了滚动一次重复提示相同错误 [BScroll warn]: Can not resolve the wrapper DOM. Vue bett ...

  2. JAVA读取EXCEL_自动生成实体类

    代码实现PropertyAnno.java import java.lang.annotation.ElementType; import java.lang.annotation.Retention ...

  3. Java通过jni调用动态链接库

    (1)JNI简介 JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++).从Java1.1开始,JNI标准成为java ...

  4. hive优化之小文件合并

    文件数目过多,会给HDFS带来压力,并且会影响处理效率,可以通过合并Map和Reduce的结果文件来消除这样的影响: set hive.merge.mapfiles = true ##在 map on ...

  5. 【原创】中断子系统-ARM GPIO中断处理流程

    目录 第一部分 GIC中断控制器的注册 1. GIC驱动分析 2.GIC驱动流程分析 第二部分 device node转化为platform_device 第三部分:platform_device注册 ...

  6. Head First 设计模式 —— 08. 外观 (Facade) 模式

    思考题 想想看,你在 JavaAPI 中遇到过哪些外观,你还希望 Java 能够新增哪些外观? P262 println.log 日志接口.JDBC 接口 突然让想感觉想不出来,各种 API 都用得挺 ...

  7. 【高精度】计算2的N次方

    题目相关 [题目描述] 任意给定一个正整数N(N≤100),计算2的n次方的值. [输入] 输入一个正整数N. [输出] 输出2的N次方的值. [输入样例] 5 [输出样例] 32 分析 本题考察的是 ...

  8. Python实验6--网络编程

    题目1 1.编写程序实现基于多线程的TCP客户机/服务器程序. (1)创建服务器端套接字Socket,监听客户端的连接请求: (2)创建客户端套接字Socket,向服务器端发起连接: 服务器端套接字 ...

  9. Logrotate工具使用

    Logrotate ​ logrotate是一个被设计来简化系统管理日志文件的工具,在系统运行时,如果产生大量的日志文件,可以使用该工具进行管理,如/var/log/*文件夹是存储系统和应用日志的目录 ...

  10. oracle分区表分区栏位NULL值测试

    实验在分区栏位为NULL时,分区表的反应 1.创建普通的分区表 CREATE TABLE MONKEY.TEST_PART_NULL_NORMAL ( ID NUMBER, ADD_DATE DATE ...