什么是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. while循环写3次用户名密码验证程序

    #变量来自原始用户名和密码 username = 'admin' password = 'nimda' #变量来自计数器 count = 0 #循环条件计数器小于3,则执行while代码块 while ...

  2. CSS(一) 引入方式 选择器 权重

    Css(一) Cascading Style Sheet 层叠样式表 css注释方式/*  */ 一.Css引入方式 1. 行间样式 style=" key:value; " &l ...

  3. 原来你是这样的JAVA[03]-继承、多态、抽象类

    一.继承 Java中的继承使用关键字extends ,跟C#的语法略有差别. 1.子类构造器 java会自动在子类的构造器中插入对父类构造器的调用,也就是说在子类可以访问父类之前已经完成了父类的初始化 ...

  4. Java与算法之(10) - 希尔排序

    希尔排序是插入排序的一种,是直接插入排序的改进版本. 对于上节介绍的直接插入排序法,如果数据原来就已经按要求的顺序排列,则在排序过程中不需要进行数据移动操作,即可得到有序数列.但是,如果最初的数据是按 ...

  5. CTF---Web入门第十四题 忘记密码了

    忘记密码了分值:20 来源: Justatest 难度:中 参与人数:7706人 Get Flag:2232人 答题人数:2386人 解题通过率:94% 找回密码 格式:SimCTF{ } 解题链接: ...

  6. 深度优先搜索(DFS)专题讲座PPT截图【需要原稿的请留言或私信】

    以下是今晚我在bilibili直播讲DFS算法的时候的ppt截图,ppt搞了一下午,水平有限,只能做成这个样子,供大家参考!(如果需要原稿,请在评论区留言或私信告诉我,我会发到你的邮箱里),感谢各位的 ...

  7. Codeforces Round #416 (Div. 2)(A,思维题,暴力,B,思维题,暴力)

    A. Vladik and Courtesy time limit per test:2 seconds memory limit per test:256 megabytes input:stand ...

  8. VS2012 TFS解决离职后代码遗留未迁入问题

    第一步: 在命令行中输入 C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE 第二步: 根据用户查找该用户下workspac ...

  9. cookie 和 session的区别

    一.总结: 1.cookie数据存放在客户的浏览器上,session数据放在服务器上. 2.cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗 考虑到安全应当使用ses ...

  10. Cxf -wsdl2java 使用参数介绍

    wsdl2java -h 可以得到详细的参考文档: G:\cxf\apache-cxf-3.1.6\bin>wsdl2java -h wsdl2java -fe|-frontend <fr ...