事件驱动架构(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. spring的ioc容器生成的对象也是代理对象对吗

    一直以为spring的ioc容器生成的对象都是代理对象,其实这个是错误的.spring ioc默认的都是原生对象  只有通过aop增强的对象才是代理对象 有@Transactional  注解或者配置 ...

  2. 如果不空null并且不是空字符串才去修改这个值,但这样写只能针对字符串(String)类型,如果是Integer类型的话就会有问题了。 int i = 0; i!=''。 mybatis中会返回tr

    mybatis 参数为Integer型数据并赋值0时,有这样一个问题: mybatis.xml中有if判断条件判断参数不为空时,赋值为0的Integer参数被mybatis判断为空,因此不执行< ...

  3. [leetcode]79.Search Word 回溯法

    /** * Given a 2D board and a word, find if the word exists in the grid. The word can be constructed ...

  4. rocketmq部署架构

    1 技术架构 RocketMQ架构上主要分为四部分,如上图所示: Producer:消息发布的角色,支持分布式集群方式部署.Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息 ...

  5. 美团关于分布式ID实践方案

    在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识.如在美团点评的金融.支付.餐饮.酒店.猫眼电影等产品的系统中,数据日渐增长,对数据分库分表后需要有一个唯一ID来标识一条数据或消息,数据库的 ...

  6. Turtlebot3新手教程-应用-跟随

    本文针对如何利用Turtlebot3可实现的各种应用进行讲解 具体步骤如下: [Remote PC]安装应用包 cd ~/catkin_ws/src git clone https://github. ...

  7. ES6 Set.Map.Symbol数据结构

    一.ES6 Set数据结构 ES6新推出了Set数据结构,它与数组很类似,Set内部的成员不允许重复,每一个值在Set中都是唯一的,如果有重复的值出现会自动去重(也可以理解为忽略掉),返回的是集合对象 ...

  8. http ContentLength 为0 下载问题

    如图 通过http 下载某个东西 ,    WebResponse response = request.GetResponse(); response 调试如图 ContentLength 为0  ...

  9. Windows软件Everything的配置

    Everything配置 Everything是一款Windows下的搜索软件,怎么安装应该不难.这里说一下个人使用的两个习惯. 主要就两点,一个是快捷键,一个是搜索路径 1. 快捷键 配置快捷键,点 ...

  10. 【C++】《C++ Primer 》第四章

    第四章 表达式 一.基础 重载运算符:当运算符作用在类类型的运算对象时,用户可以自行定义其含义. 左值和右值: C中:左值可以在表达式左边,右值不能. C++中:当一个对象被用作右值的时候,用的是对象 ...