热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

dubbo解析时间轮算法的实现HashedWheelTimer原理

本文基于dubbo2.7.5版本代码本文介绍一下dubbo使用的时间轮算法HashedWheelTimer。dubbo里面涉及到定时任务调度的都是使用HashedWheelTime

本文基于dubbo 2.7.5版本代码

本文介绍一下dubbo使用的时间轮算法HashedWheelTimer。
dubbo里面涉及到定时任务调度的都是使用HashedWheelTimer。比如:客户端等待服务端返回,如果超时了,HashedWheelTimer调度定时任务触发超时异常。
为什么要是用时间轮算法?下面这些引用自文章:https://zhuanlan.zhihu.com/p/32906730。

大量的调度任务如果每一个都使用自己的调度器来管理任务的生命周期的话,浪费cpu的资源并且很低效。
时间轮是一种高效来利用线程资源来进行批量化调度的一种调度模型。把大批量的调度任务全部都绑定到同一个的调度器上面,使用这一个调度器来进行所有任务的管理(manager),触发(trigger)以及运行(runnable)。能够高效的管理各种延时任务,周期任务,通知任务等等。
缺点,时间轮调度器的时间精度可能不是很高,对于精度要求特别高的调度任务可能不太适合。因为时间轮算法的精度取决于,时间段“指针”单元的最小粒度大小,比如时间轮的格子是一秒跳一次,那么调度精度小于一秒的任务就无法被时间轮所调度。而且时间轮算法没有做宕机备份,因此无法再宕机之后恢复任务重新调度。

dubbo的HashedWheelTimer实现和netty的是一致的。
一般调用时间轮增加定时任务的代码如下:

HashedWheelTimer failTimer = new HashedWheelTimer(new NamedThreadFactory("failback-cluster-timer", true), 1,TimeUnit.SECONDS, 32, failbackTasks);RetryTimerTask retryTimerTask = new RetryTimerTask(loadbalance, invocation, invokers, lastInvoker, retries, RETRY_FAILED_PERIOD);failTimer.newTimeout(retryTimerTask, RETRY_FAILED_PERIOD, TimeUnit.SECONDS);

首先创建一个时间轮对象,然后创建一个TimerTask对象,调用时间轮对象的newTimeout方法将TimerTask加入到调度器中。
时间轮算法的原理是:
来源https://zhuanlan.zhihu.com/p/32906730
上图的的圆环表示的就是时间轮,时间轮被分割成了一个个扇形块,每个扇形块代表一段时间间隔,时间轮上的指针最初指向0扇形块,时间轮上还有一个指针,指针指到哪个扇形块,就意味着该扇形块对应的任务到时间了,需要执行了。任务由绿色的方块表示。假如扇形块代表的时间间隔为200ms,那么每过200ms,指针指向下一个扇形块。如果指针不指向某一扇形块,就算该扇形块的任务已经到期了,也不会执行。由此可以看出,时间间隔设置的越短,任务的到期执行时间就越精确。
有的任务到期时间比较长,时间轮需要转几圈后才到期,因此对每个任务增加一个字段,用于表示圈数,指针每转一圈,圈数减1,上图绿色方块前面的数字便是圈数。因此满足执行条件的任务是:指针指向当前扇形块且圈数为0。
因为同时到期的任务不止一个,因此位于同一个扇形块的任务用链表连接。
下面介绍一下dubbo针对时间轮的实现。
首先介绍HashedWheelTimer的构造方法的各个入参:

ThreadFactory threadFactory,//创建线程的线程工厂对象,每个时间轮对象持有一个线程
long tickDuration, //扇形块的时间间隔
TimeUnit unit, //tickDuration的单位
int ticksPerWheel,//圆环上一共有多少个时间间隔,HashedWheelTimer对其正则化,将其换算为大于等于该值的2^n
long maxPendingTimeouts//最多允许多少个任务等待执行

HashedWheelTimer有多个私有类:

  • Worker:实现了Runnable接口,时间轮里面的线程执行的是它的run方法。
  • HashedWheelTimeout:代表一个任务,也就是上图的绿色方块。HashedWheelTimer.newTimeout方法内部创建该对象,并将它加入到队列中。
  • HashedWheelBucket:代表上图的扇形块。时间轮上的扇形块组成一个数组,HashedWheelTimer循环遍历该数组。HashedWheelBucket持有一个HashedWheelTimeout链表,表示该扇形块对应的任务。

在创建HashedWheelTimer对象后,线程并没有执行,只有当调用了newTimeout方法时,才会启动线程,这属于懒启动的策略。当然也可以直接调用start()方法启动线程。
还有一点需要注意,调用newTimeout方法后,并没有将任务加入到时间轮中,而是将任务放到了一个队列里面,等待时间轮的指针指向下一个扇形块的时候,才会将任务从队列里放入到时间轮上。每次最多处理100000个任务。
时间轮对象也不能创建太多,INSTANCE_COUNTER属性记录了HashedWheelTimer对象个数,最多不能超过64个。
当首次调用newTimeout或者start方法后,便会调用属性workerThread的start方法启动线程,workerThread是Thread对象。线程启动后,开始执行Worker类的run方法。
下面介绍run方法流程:
在这里插入图片描述

参考:

https://zhuanlan.zhihu.com/p/32906730


推荐阅读
  • 本文由编程笔记#小编为大家整理,主要介绍了源码分析--ConcurrentHashMap与HashTable(JDK1.8)相关的知识,希望对你有一定的参考价值。  Concu ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 本文介绍了在Python张量流中使用make_merged_spec()方法合并设备规格对象的方法和语法,以及参数和返回值的说明,并提供了一个示例代码。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
  • 从相邻元素对还原数组的解题思路和代码
    本文介绍了从相邻元素对还原数组的解题思路和代码。思路是使用HashMap存放邻接关系,并找出起始点,然后依次取。代码使用了HashMap来存放起始点所在的adjacentPairs中的位置,并对重复的起始点进行处理。 ... [详细]
  • 本文是一篇翻译文章,介绍了async/await的用法和特点。async关键字被放置在函数前面,意味着该函数总是返回一个promise。文章还提到了可以显式返回一个promise的方法。该特性使得async/await更易于理解和使用。本文还提到了一些可能的错误,并希望读者能够指正。 ... [详细]
  • HashMap的扩容知识详解
    本文详细介绍了HashMap的扩容知识,包括扩容的概述、扩容条件以及1.7版本中的扩容方法。通过学习本文,读者可以全面了解HashMap的扩容机制,提升对HashMap的理解和应用能力。 ... [详细]
author-avatar
手机用户2502859523
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有