关于云计算:disruptor笔记之二Disruptor类分析

29次阅读

共计 3236 个字符,预计需要花费 9 分钟才能阅读完成。

欢送拜访我的 GitHub

https://github.com/zq2599/blog_demos

内容:所有原创文章分类汇总及配套源码,波及 Java、Docker、Kubernetes、DevOPS 等;

《disruptor 笔记》系列链接

  1. 疾速入门
  2. Disruptor 类剖析
  3. 环形队列的根底操作 (不必 Disruptor 类)
  4. 事件生产知识点小结
  5. 事件生产实战
  6. 常见场景
  7. 期待策略
  8. 知识点补充 (终篇)

本篇概览

  • 通过前文的实战,咱们对 Disruptor 有了初步意识,借助 com.lmax.disruptor.dsl.Disruptor 类能够轻松实现以下操作:
  • 环形队列初始化
  • 指定事件消费者
  • 启动消费者线程
  • 接下来要面对两个问题:
  • 深刻理解 Disruptor 类是如何实现上述操作的;
  • 对 Disruptor 类有了足够理解时,尝试不必 Disruptor,本人入手操作环形队列,实现音讯的生产和生产,这样做的目标是加深对 Disruptor 外部的意识,做到知其所以然;
  • 接下来咱们先解决第一个问题吧,联合 Disruptor 对象的源码来看看上述三个操作到底做了什么;

环形队列初始化

  • 环形队列初始化产生在实例化 Disruptor 对象的时候,即 Disruptor 的构造方法:
public Disruptor(final EventFactory<T> eventFactory, final int ringBufferSize, final ThreadFactory threadFactory)
    {this(RingBuffer.createMultiProducer(eventFactory, ringBufferSize), new BasicExecutor(threadFactory));
    }
  • <font color=”blue”>RingBuffer.createMultiProducer</font> 办法外部实例化了 RingBuffer,如下图红框:

  • 记下 <font color=”red”> 第一个重要知识点 </font>:创立 RingBuffer 对象;

指定事件消费者

  • 在前文中,上面这行代码指定了事件由 StringEventHandler 生产:
disruptor.handleEventsWith(new StringEventHandler(eventCountPrinter));
  • 查看 handleEventsWith 办法的外部:
public final EventHandlerGroup<T> handleEventsWith(final EventHandler<? super T>... handlers)
{return createEventProcessors(new Sequence[0], handlers);
}
  • 开展 createEventProcessors 办法,如下图,请重点关注创立 SequenceBarrier 和 BatchEventProcessor 等操作:

  • 开展上图红框四中的 updateGatingSequencesForNextInChain 办法,如下图,红框中的 ringBuffer.addGatingSequences 须要重点关注:

  • 小结一下,disruptor.handleEventsWith 办法波及到 <font color=”red”> 四个重要知识点 </font>:
  1. 创立 SequenceBarrier 对象,用于接管 ringBuffer 中的可生产事件
  2. 创立 BatchEventProcessor,负责生产事件
  3. 绑定 BatchEventProcessor 对象的异样解决类
  4. 调用 ringBuffer.addGatingSequences,将消费者的 Sequence 传给 ringBuffer

启动消费者线程

  • 前文已通过日志确定了生产事件的逻辑是在一个独立的线程中执行的,启动消费者线程的代码如下:
disruptor.start();
  • 开展 start 办法,如下可见,要害代码是 <font color=”blue”>consumerInfo.start(executor)</font>:
    public RingBuffer<T> start()
    {checkOnlyStartedOnce();
        for (final ConsumerInfo consumerInfo : consumerRepository)
        {consumerInfo.start(executor);
        }

        return ringBuffer;
    }
  • ConsumerInfo 是接口,对应的实现类有 EventProcessorInfo 和 WorkerPoolInfo 两种,这里应该是哪种呢?既然起源是 consumerRepository,这就要看当初是怎么存入 consumerRepository 的,后面在剖析 createEventProcessors 办法时,下图红框中的 consumerRepository.add 被忽略了,当初须要进去看看:

  • 进去后高深莫测,可见 ConsumerInfo 的实现是 EventProcessorInfo:

  • 所以,回到后面对 <font color=”blue”>consumerInfo.start(executor)</font> 办法的剖析,这里要看的就是 EventProcessorInfo 的 start 办法了,如下图,非常简单,就是启动一个线程执行 eventprocessor(这个 eventprocessor 是 BatchEventProcessor 对象):

  • 小结一下,disruptor.start 办法波及到 <font color=”red”> 一个重要知识点 </font>:
  1. 启动独立线程,用来执行生产事件的业务逻辑;

生产事件的逻辑

  • 为了了解音讯解决逻辑,还要重点关注 BatchEventProcessor.processEvents 办法,如下图所示,其实也很简略,就是不停的从环形队列取出可用的事件,而后再更新本人的 Sequence,相当于标记曾经生产到哪里了:

总结

最初总结 Disruptor 类的重要性能:

  1. 创立环形队列(RingBuffer 对象)
  2. 创立 SequenceBarrier 对象,用于接管 ringBuffer 中的可生产事件
  3. 创立 BatchEventProcessor,负责生产事件
  4. 绑定 BatchEventProcessor 对象的异样解决类
  5. 调用 ringBuffer.addGatingSequences,将消费者的 Sequence 传给 ringBuffer
  6. 启动独立线程,用来执行生产事件的业务逻辑
  • 聪慧的您肯定会发现,本文并没有全面剖析 Disruptor 类的源码,例如 after、shutdown 等办法都没有提到,的确如此,欣宸在此给您赔罪了,本篇的重点是找出那些与基本功能无关代码,为前面的实战提供理论指导(不必 Disruptor 类实现音讯生产生产的实战),因而很多高级性能都跳过了;

了解官网流程图

  • 此时再看官网流程图,聪慧的您应该很快就能了解此图表白的意思:每个消费者都有本人的 Sequence,通过此 Sequence 获得本人在环形队列中生产的地位,再通过 SequenceBarrier 来期待可用事件的呈现,等到事件呈现了就用 get 办法取出具体的事件,给 EventHandler 来解决:

后续预报

  • 此时,咱们对 Disruptor 类曾经有了比拟深刻的了解,接下来的文章,咱们会尝试不必 Disruptor 类,仅凭着对 RingBuffer 对象的操作来实现以下三种性能:
  1. 100 个事件,单个消费者生产;
  2. 100 个事件,三个消费者,每个都单独生产这个 100 个事件;
  3. 100 个事件,三个消费者独特生产这个 100 个事件;

你不孤独,欣宸原创一路相伴

  1. Java 系列
  2. Spring 系列
  3. Docker 系列
  4. kubernetes 系列
  5. 数据库 + 中间件系列
  6. DevOps 系列

欢送关注公众号:程序员欣宸

微信搜寻「程序员欣宸」,我是欣宸,期待与您一起畅游 Java 世界 …
https://github.com/zq2599/blog_demos

正文完
 0