Hmily 源码解析 (三) —— 高效异步任务框架的使用

Hmily 源码解析 (三) —— 高效异步任务框架的使用目录这是hmily的一个核心,hmily之所以高效就是因为hmily把日志的存储维护操作及confirm,cancel的操作通过Disruptor的异步任务框架的方式执行。关于disruptor的原理如下,我没怎么研究过。后我主要分析hmily是如何使用Disruptor这个框架。高性能队列Disruptor的使用剖析Disruptor:为什么会这么快?(一)Ringbuffer的…

大家好,又见面了,我是你们的朋友全栈君。


1. DisruptorProvider

  • Disruptor队列提供者。DisruptorProvider实例里面维护了一个Disruptor队列实例ringBuffer。实际上DisruptorProvider的作用就是封装了一下ringBuffer队列,并提供统一的发布入口。也就是生产者调用的入口。
  • 首先新建DisruptorProvider实例的时候就传入了一个ringBuffer实例,生产者通过调用data方法将任务发布到ringBuffer上。
  • 简单说一下data函数。这是Disruptor 框架发布事件的逻辑,分为三个步骤
    1. 先从 RingBuffer 获取下一个可以写入的事件的序号;
    2. 获取对应的事件对象,将业务信息写入事件对象;事件对象Disruptor 要我们自定义,如下hmily定义了一个DataEvent类作为事件对象。事件对象只是一个载体,在生产者生成任务与消费者消费任务时,并不新增与销毁事件对象。事件对象内存储的才是真实被生产(/消费)的业务信息。
    3. 将事件提交到 RingBuffer;后面消费者就会读取到该position,处理该业务信息。

在这里插入图片描述

2. DisruptorProviderManage

  • 队列管理者。该类负责创建DisruptorProvider实例,也就是Disruptor队列,并提供与维护该队列。可以说如果有一个DisruptorProviderManage实例创建,那么就会有一个Disruptor任务队列。

  • DisruptorProviderManage也是泛型的,它的泛型同DisruptorProvider的泛型一致,是指向被生成与消费业务信息类

  • 这里可以先说一下,每一个加入himly框架的微服务,在启动后都会创建两个DisruptorProviderManage实例,对应的两个业务信息类分别是处理事务日志异步维护confirm,cancel的异步执行。具体后面再说。

  • 我们先来分析一下DisruptorProviderManage内的属性

    • DEFAULT_SIZE 队列的默认的大小, 使用时不设定ringbuffer的size默认为该值。另外说一下RingBuffer 大小,得是 2 的 N 次方;个数是2的N次方更有利于基于二进制的计算机进行计算,这涉及到ringbuffer性能。
    • DEFAULT_CONSUMER_SIZE 消费者默认个数,这里是设定为JVM可以使用的处理器数量*2。这里的设定我不太理解,为什么要乘以2?
    • size 队列大小
    • consumerSize 消费者个数
    • provide Disruptor队列提供者。创建后提供给外部使用生产任务到ringbuffer队列中。
    • factory 消费者工厂类,用于创建消费者去执行任务的。这里的消费处理hmily设计的比较复杂,先按下不表,后面再述。
  • 构造器方法就不讲了,就是为了传递如上的参数进来。
    在这里插入图片描述
    在这里插入图片描述

  • 在调用者在创建DisruptorProviderManage实例后,就会调用DisruptorProviderManage的start方法,创建ringbuffer队列。创建ringbuffer的过程下面简单介绍一下。

    • 第一步创建disruptor实例,我们看到Disruptor的泛型就是事件对象。我们来看一下Disruptor类的构造器都传入什么参数做了什么。
      • 第一个参数是EventFactory(事件对象工厂),负责为disruptor在初始化时提供事件对象(DataEvent)实例
      • 第二个参数是ringbuffer的size,这个队列的容量。
      • 第三个参数是ThreadFactory,是用于事件处理的线程池,也就是调用消费者处理任务的线程。通过HmilyThreadFactory类生成,关于HmilyThreadFactory类先按下不表。
      • 第四个参数是ProducerType.MULTI?不清楚什么意思,允许生产者并发新增任务?
      • 第五个参数是WaitStrategy,等待处理策略。就是当ringbuffer的size被存储满了之后,仍然有生产者添加新的任务时应该如何处理。这里采用BlockingWaitStrategy (阻塞策略,没有空间了线程就阻塞着)。BlockingWaitStrategy 是最低效的策略,但其对CPU的消耗最小并且在各种不同部署环境中能提供更加一致的性能表现。
    • 第二步disruptor实例设置消费者集合。关于DisruptorConsumer我们也先按下不表。
    • 第三步设置默认异常处理方案为不处理(for why?)。
    • 第四步,启动disruptor。
    • 第五步获取ringBuffer实例并根据ringBuffer实例创建DisruptorProvider实例。后面的生产者就是通过调用DisruptorProvider实例来新增异步任务的。
  • getProvider方法,返回DisruptorProvider实例供生产者添加异步任务。
    在这里插入图片描述

  • 前面介绍了说有两个DisruptorProviderManage实例,我们来看一下它们是如何发布任务的把。

  • 执行confirm,cancel命令的队列

    • 定义
      在这里插入图片描述
  • 初始化
    在这里插入图片描述

  • HmilyTransactionHandlerAlbum (真实的业务信息——接口),run方法的实现由生产者来定义,后面消费者会执行这个run方法来实现消费这个业务信息,这是后话了。
    在这里插入图片描述

  • 生产者发布,如下获取provide,发布这个(java8提供的语法,会自动继承HmilyTransactionHandlerAlbum ,并实现run方法),后面消费者最终调用的也就是run方法(内的 hmilyTransactionExecutor.confirm语句),从而实现异步执行。
    在这里插入图片描述

  • 异步执行日志维护

    • 定义
      在这里插入图片描述
    • 初始化
      在这里插入图片描述
    • HmilyTransactionEvent 业务信息载体(事务日志及操作状态——更新,新增或删除)
      在这里插入图片描述
    • 生产者使用,这里由封装了一层,但无关大雅。至于消费者是如何使用这个信息的我们后面再说。
      在这里插入图片描述

关于消费者

  • 关于消费者,hmily用了一个挺复杂的框架(用到的类很多),但我觉得是挺必要的,我在消费者的搭建这块也学到了挺多的。不过记录起来是挺麻烦的,下面我一一道来。

3. DisruptorConsumer

  • 如上,Disruptor提供的消费者接口是WorkHandler。hmily在此的实现就是DisruptorConsumer 类。
  • 如下,DisruptorConsumer 下并没有直接去执行业务数据,而是又封装了一层DisruptorConsumerFactory (消费者工厂)。这一层封装的作用我以为是为了和泛型T对应。不同的T会有不同的DisruptorConsumer实例及传入对应DisruptorConsumerFactory实现良好的扩展。
    在这里插入图片描述

4. DisruptorConsumerFactory

  • DisruptorConsumerFactory也是一个接口,而且这里又封装了一层AbstractDisruptorConsumerExecutor去真正执行业务信息,这我就不是很理解了。明明在DisruptorConsumer 里直接传入AbstractDisruptorConsumerExecutor不就行了么?或者这是什么设计模式么,存疑待学习

在这里插入图片描述

5. AbstractDisruptorConsumerExecutor

  • 关于这个抽象类里面不仅定义了executor方法,还定义了一个subscribers集合,看起来这就是在消费者这边做了两层扩展的原因吧,但是作者暂时没使用到这个集合,它的企图我们这边暂时不得而知。

6. HmilyConsumerLogDataHandler

  • 是异步维护日志信息时的实现类。继承了AbstractDisruptorConsumerExecutor类及实现了DisruptorConsumerFactory接口。
  • 所以在DisruptorConsumer 里面的两层扩展都是这一个类的实例?我觉得可能是这样的,作者有一些企图需要做两层的扩展实现某些需求,但是真的实现只需要一个实现类就可以。这样似乎更清晰?有一种说不上来觉得这种写法挺好的感觉,值得学习一下。定义分层,实现归一

在这里插入图片描述

  • executor方法里面就是处理业务信息的逻辑了,再往下我们就不深入了,与消费者的框架无关了。

在这里插入图片描述

7. HmilyConsumerTransactionDataHandler

  • 是异步执行cofrm,cancel的实现类。原理同6

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143593.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 大数据开发是干什么的?[通俗易懂]

    大数据开发是干什么的?[通俗易懂]据数联寻英发布《大数据人才报告》显示,目前全国的大数据人才仅46万,未来3-5年内大数据人才的缺口将高达150万,越来越多人加入到大数据培训,都希望在大数据培训机构中学习最前沿的知识,找一份不错的工作。大数据开发工程师主要负责的工作有以下内容:1.负责公司大数据平台的开发和维护,负责大数据平台持续集成相关工具平台的架构设计与产品开发等工作;2.主要从事网络日志的大数据分析工作,包括…

    2022年5月9日
    53
  • XDOJ1145–组合数学四之Carnival Phantasm

    XDOJ1145–组合数学四之Carnival Phantasm描述:为解救可怜的武内崇老师,saber、远坂、爱尔奎特、希耶尔等人组成了第六科急救队!最终,由琥珀开发出了禁药,分身光线(这药是内服还是外用的==?),将爱尔奎特批量化生产,来对月世界进行全面的地毯式搜索。现已知,第六科共有m个复制人(每个复制人完全一样),月世界有n个城市,每个城市会被一个复制人搜索一遍。问:共有多少种分配方法。(根据时空管理局劳务法更定,每个复制人又要分得工作。)…

    2022年5月7日
    36
  • AvalonDock使用心得「建议收藏」

    AvalonDock使用心得「建议收藏」  桌面程序的应用,不可避免的就会用到大量的布局控件,之前的一个项目也想过去做类似于VisualStudio的那种灵活的布局控件,也就是界面上的控件能够实现拖拽放置、隐藏、窗口化等一系列的操作,但由于开发时间以及需求的原因,没有太严格要求这方面功能的实现,也就只能算是想过一下而已,实际用的时候还是固定布局,但是最近接触到新的项目,需要这方面的应用就不得不自己动手查找和做这样的东西了。  有朋…

    2022年7月20日
    14
  • ftp服务器映射到外网_内网穿透安全吗

    ftp服务器映射到外网_内网穿透安全吗转载:https://service.oray.com/question/752.html花生壳服务目前的用户量已达1600万以上,广泛应用于网站建设、视频监控、遥感测绘、FTP、VPN、企业OA、ERP等应用领域。花生壳服务可以将您的动态公网IP和域名进行实时绑定。简单来说,就像您的手机一样,无论在那里,只要通过一个号码就可以找到您了,而这个号码就相于在贝锐使用花生壳服务的域名。现在我们以实例讲解如何使用花生壳来协助搭建FTP服务,从而实现FTP服务的外网访问。需要使用的软件工具:花生壳8客户端和SE

    2025年10月30日
    2
  • cocoapods使用_软线连接

    cocoapods使用_软线连接背景

    2022年9月27日
    1
  • 国税总局发票查验平台验证码识别方案,识别率达98%「建议收藏」

    国税总局发票查验平台验证码识别方案,识别率达98%「建议收藏」这是一篇含金量很高的干货文章,国家税务总局全国增值税发票查验平台验证码识别方案和具体思路,实验结果测试了200+次,识别率达到98%以上,识别速度的话,CPU大概5-8毫秒左右,模型大概3mb。

    2022年7月17日
    24

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号