什么是EventBus
EventBus是对发布-订阅模式的一种实现。其以一种非常优雅的方式实现了组件间的解耦与通信,在Android开发、DDD等领域都有非常广泛的应用。

事件流大致如下:

  • Producer向EventBus发送事件。
  • EventBus向所有监听了该事件的Consumer推送事件。
  • 监听了该事件的Consumer消费事件。

注:一个组件即可以是Producer,也可以是Consumer。

分布式服务间的EventBus
在分布式系统中,事件在服务之间的传递要比单机EventBus复杂很多。有没有一种适用于分布式服务之间的,并且事件传递就像单机一样简单的EventBus呢?在GitHub上搜索了JAVA实现的EventBus,排名前十的几乎都是用于Android或JAVA的单机事件总线。良久之后...还是自己动手吧。集群环境下的EventBus比单机版需要多考虑一些问题,比如:

  1. 服务集群部署的情况下,如何保证每个集群均可订阅该事件,且每个集群只能消费一次该事件。
  2. 如何实现一个服务内部多个`xxxService`订阅同一事件。

解决方案:

  1. 使用`kafka`实现集群间的发布订阅(基于`topic`),同一集群处于同一个kafka的consumer-group来保证每个集群只会消费一次该事件。
  2. 服务在启动时可反射获得所有实现了`IEventHandler<TEventArg>`的类并缓存,服务消费消息时获取所有注册了该消息的handler并调用其`HandleEvent`方法。

部分关键源码

1、事件消息的定义

public abstract class EventArg implements IEventArg{

    private Date eventTime;

    public EventArg(){
eventTime = new Date();
} public Date getEventTime() {
return eventTime;
} public void setEventTime(Date eventTime) {
this.eventTime = eventTime;
}
}

事件消息默认记录创建时间,可扩展其他字段,比如发送时间、标识等。

2、使用spring-kafka发送消息

/**
* kafka事件注册器,向kafka队列中push消息
*/
@Component
public class KafkaRegister implements IEventRegister { @Autowired(required = false)
private KafkaTemplate<String,IEventArg> kafkaTemplate; /**
* 事件注册
*
* @param eventArg 事件参数
*/
@Override
public void regist(IEventArg eventArg) {
kafkaTemplate.send(getTopic(eventArg),eventArg);
} /**
* 获取kafka的topic
*
*
* @param eventArg
* @return topic
*/
private String getTopic(IEventArg eventArg){
return eventArg.getClass().getName();
}
}

3、消费kafka消息并执行当前服务中所有订阅了该消息的事件

/**
* kafka事件监听器
*/
public class KafkaEventArgListener implements MessageListener<String,EventArg> { @Autowired
private IEventHandlerFactory eventHandlerFactory; @Override
public void onMessage(ConsumerRecord<String, EventArg> consumerRecord) {
if (consumerRecord == null) return;
EventArg value = consumerRecord.value(); Set<IEventHandler> handlers = eventHandlerFactory.getHandlers(value);
if (handlers == null) return;
for (IEventHandler handler : handlers) {
handler.HandleEvent(value);
}
}
}

EventBus的使用

1、事件的定义。所有事件均继承于上文EventArg抽象类,示例如下:

public class TestEventArg extends EventArg{
private String value; public String getValue() {
return value;
} public void setValue(String value) {
this.value = value;
}
}

2、事件发布。示例代码:

eventBus.push(new TestEventArg());

3、事件订阅。一个服务发布事件之后,任何服务中的任何`xxxServiceImpl`类均可订阅该事件,实现`IEventHandler<TEventArg>`接口即可完成事件的订阅,示例如下:

public class FormServiceImpl extends AbstractServiceImpl<Form> implements FormService,IEventHandler<TestEventArg> {

    @Override
public void HandleEvent(TestEventArg eventArg) {
System.out.println("notify zero======");
}
}

整体来说,使用还是很简单的,EventBus实现与使用示例收录于bird-java项目中,项目地址:https://github.com/liuxx001/bird-java

【bird-java】分布式服务间的事件总线EventBus的更多相关文章

  1. vue中央事件总线eventBus的简单理解和使用

    公共事件总线eventBus的实质就是创建一个vue实例,通过一个空的vue实例作为桥梁实现vue组件间的通信.它是实现非父子组件通信的一种解决方案. 用法如下: 第一步:项目中创建一个js文件(我通 ...

  2. ASP.NET Core基于微软微服务eShopOnContainer事件总线EventBus的实现

    这个EventBus的实现是基于微软微服务https://github.com/dotnet-architecture/eShopOnContainers项目的,我把它从项目中抽离出来,打包成nuge ...

  3. java分布式服务框架Dubbo的介绍与使用

    1. Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案.简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需 ...

  4. 转载:java分布式服务框架Dubbo的介绍与使用

    1. Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案.简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需 ...

  5. Java分布式服务框架Dubbo初探(待实践)

    Dubbo是什么? Dubbo[]是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案. 其核心部分包含: 远程通讯: 提供对多种基于长连接的NIO框架抽象封 ...

  6. 基于ASP.NET Core 5.0使用RabbitMQ消息队列实现事件总线(EventBus)

    文章阅读请前先参考看一下 https://www.cnblogs.com/hudean/p/13858285.html 安装RabbitMQ消息队列软件与了解C#中如何使用RabbitMQ 和 htt ...

  7. 事件总线 EventBus

    661. .net中事件模型很优雅的实现了观察者模式,同时被大量的使用在各种框架中. [2016-04-30 10:52:42]662. Prism框架中实现了一个典型的EventAggregator ...

  8. Guava: 事件总线EventBus

    EventBus 直译过来就是事件总线,它使用发布订阅模式支持组件之间的通信,不需要显式地注册回调,比观察者模式更灵活,可用于替换Java中传统的事件监听模式,EventBus的作用就是解耦,它不是通 ...

  9. 自己动手写事件总线(EventBus)

    本文由云+社区发表 事件总线核心逻辑的实现. EventBus的作用 Android中存在各种通信场景,如Activity之间的跳转,Activity与Fragment以及其他组件之间的交互,以及在某 ...

随机推荐

  1. android自定义文本框,后面带清空按钮

    android常见的带清空按钮的文本框,获得焦点时如果有内容则显示,否则不显示 package com.qc.health.weight; import com.qc.health.R; import ...

  2. 基于 socket.io 的 AI 服务 杂谈

    为什么会想到来聊下这个话题. 前几天在公司的项目中,开发一个基于 socket.io 的直播 IM 功能. 直播分为两部分,一部分是比较昂贵的 视频推流, 另外一部分是 IM 即时聊天服务. 从这里开 ...

  3. python并发之多线程

    一开启线程的两种方式 from threading import Thread import time def haha(name): time.sleep(2) print('%s 你大爷..... ...

  4. C# war3 巨魔精灵 minimap

    弃坑LOL后,无聊的时候玩玩 war3的RPG地图,巨魔与精灵.  玩了一段时间精灵....然后玩魔结果总是找不到人.所以就有了这个想法. 代码纯粹靠搬运. 说下原理,网上有份代码,可以查看当前选中目 ...

  5. (GO_GTD_2)基于OpenCV和QT,建立Android图像处理程序

    一.综述     如何采集图片?在windows环境下,我们可以使用dshow,在linux下,也有ffmpeg等基础类库,再不济,opencv自带的videocapture也是提供了基础的支撑.那么 ...

  6. 3.If statements

    if 语句   电脑程序不只是执行命令.时常会需要做出选择.例如基于一个条件的选择.Python有这样几种条件运算:   >   greater than <   smaller than ...

  7. my discipline life

    周一  ~   周五 7.30 ---  8.00 起床,洗漱等 8.00 ---  8.30 默写8-10个英语单词 8.35 ---  9.10 吃早餐,骑自行车去公司 12.20  ---  1 ...

  8. Gym 100952A&&2015 HIAST Collegiate Programming Contest A. Who is the winner?【字符串,暴力】

    A. Who is the winner? time limit per test:1 second memory limit per test:64 megabytes input:standard ...

  9. HTTP协议----->连接管理

    1.  TCP连接 1.1  TCP为HTTP提供了一条可靠的比特传输管道. TCP(Transmission Control Protocol)----传输控制协议,是主机对主机层的传输控制协议,提 ...

  10. Java入门篇(六)——类和对象

    写到这里终于写到了入门篇的最后一个知识点了.类和对象是Java中经常被提到的两个词汇,实际上可以将类看作对象的载体,它定义了对象所具有的功能.Java是面向对象的语言,因此掌握类与对象是学习Java语 ...