guava的eventBus和disruptor比较

你。 提交于 2020-01-10 05:49:00

EventBus:

基于观察者模式实现的,本文基于同步模式来操作;这里只介绍下几个常用操作的代码实现:

register:注册观察者实现:主要就是以把观察者观察的类key,同类观察者的set集合为value构成一个ConcurrenHashMap

代码如下:

  private final ConcurrentMap<Class<?>, CopyOnWriteArraySet<Subscriber>> subscribers =
      Maps.newConcurrentMap();

这里有两步加锁:map分段锁,copyOnWriteArraySet读写锁;

EventBus.post(Object):发送事件实现:根据事件的class找subscribers中的观察者,通过反射执行所有观察者的@Subscribe注解注释的方法;

代码如下:

public void post(Object event) {
    Iterator<Subscriber> eventSubscribers = subscribers.getSubscribers(event);
    if (eventSubscribers.hasNext()) {
      dispatcher.dispatch(event, eventSubscribers);
    } else if (!(event instanceof DeadEvent)) {
      // the event had no subscribers and was not itself a DeadEvent
      post(new DeadEvent(this, event));
    }
  }

本地测试结果:生产者生成100000条事件非常快(没找到有拒绝策略,异步模式有线程池拒绝),如果动态增加大量生产者效率会下降主要是因为两个锁,另外因为消费者需要轮询执行,如果消费者延迟高,会导致内存和cpu飙升,本地16g内存测试结果:

应用场景:ddd领域模型中jvm事件总线可以使用eventBus,建议使用异步的模式

Disruptor:

基础介绍就不说了自己去看官方文档,这里只写做事件总线怎么做:

生产者:

            // 1.ringBuffer 事件队列 下一个槽
            long sequence = ringBuffer.next();
            //2.取出空的事件队列
            LongEvent longEvent = ringBuffer.get(sequence);
            data = byteBuffer.getLong(0);
            //3.获取事件队列传递的数据
            longEvent.setValue(data);
            ringBuffer.publish(sequence);

消费者(单线程):把消费者作为事件转发器,根据事件类型转发到不同的自定义事件处理器(类似于Redis的事件处理机制)

每个事件处理器都在各自的业务线程池中执行(Hystrix的线程池隔离机制),避免某个延迟操作影响其他操作(线程池数不宜过多避免达到监控平台的数量限制)

这里为什么把两种方式比较呢?

其实大部分公司eventBus肯定够用,但是他的所有的事件都是一个线程池,并没有隔离,而且还有锁,总的来说就是一个pull的模式。

disruptor是一个拉的模式,ringbuffer和消费者各自维护一个序号,用于记录消费者消费的消费位置;另外disruptor支持多种消费模式:串行,并行(a1,a2之间并行,但是a1,b1需要串行),链式并行,菱形并行模式;

对于支付类的大型公司还是disruptor的无锁效率更高,并且使用事件分派机制可以使各个业务操作在线程池层面隔离

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!