Dubbo的时间轮源码解析

简介:
大家好,我是xp,一年更新一篇,惭愧,太懒了,逐渐躺平…
在这里插入图片描述

时间轮,是一种实现延迟功能(定时器)的巧妙算法,常用于Netty、Dubbo、Kafka等等。此篇文章分析Dubbo。
说白了,就是延时任务,常用于定时重发、延迟生产、拉取等等。
最简单的写法,DelayQueueRocketMQ延时队列等等,其中DelayQueue博主已经分析过,这里不过多介绍。不过这么多有些优秀中间件都是自己实现的,为啥?装x呗
在这里插入图片描述
在这里插入图片描述
当然是为了性能了,坐稳了,开卷。
先简单看个图
在这里插入图片描述
这是一个长度为8的数组,只不过我画成了圆形。如果一秒走一步,一圈走下来就是8秒。

  • 延时2秒:wheel[1]
  • 延时5秒:wheel[4]
  • 延时10秒???
    最简单的就是将wheel加大超过10,但是这样会造成浪费,1个延时2秒的任务,1个延时100秒的任务,初始化一个长度为100的wheel,属实浪费。
    可以换个思路,一圈是8秒,10秒 = 1圈+延时2秒,最后就是:
  • 延时10秒:一圈 + wheel[1]
    说到这,貌似so easy?
    在这里插入图片描述
    好的,我们进入源码看下,是不是这样的。
    坐稳了,开始源码之旅:
    在这里插入图片描述

这是我从Dubbo中复制出来的代码,方便调试的。
使用很简单:
初始化时间轮和添加任务
先看1部分:
在这里插入图片描述
初始化时间轮还是比较简单的,简单看下传的参数:

    threadFactory:线程工厂
    tickDuration:时间轮上每个Bucket之间的间隔,可以简单理解成每次循环的时间,实际每次循环的时候会小于这个时间点,下面会说
    unit:时间单位
    ticksPerWheel:时间轮的大小
    maxPendingTimeouts:最大等待数量

还有我框出来的地方,可以稍微看下:
createWheel:
在这里插入图片描述
wheel的长度初始化为2的幂次方,
还定义了mask,为wheel的长度-1。
看到这,大部分人应该都知道为啥了,不知道可以去看博主的HashMap篇,里面有详细介绍。

继续看添加任务:
在这里插入图片描述
先不说start(),就是计算任务需要执行的时间点,然后实例化成HashedWheelTimeout,加入到timeouts。这里的timeouts是待执行队列,任务不是直接挂到时间轮的,而是先加入到待执行队列的。
重点看start():
在这里插入图片描述
看起来很简单,主要是 workerThread这个线程在干什么,workerThreadWorker线程,初始化时间轮的时候赋值的。
Worker:
在这里插入图片描述
分为4部分:

  1. 单纯的初始化startTime,这里对应着start()里面的startTimeInitialized.await(),startTime初始化成功,就可以计算任务需要执行的时间了,所以初始化完就countDown了。
  2. waitForNextTick:在这里插入图片描述也很简单,相当于每次休眠tickDuration,但是有个细节:
    //看似这里得到的值都一样,其实不然
    //因为每走一步,都会处理任务,浪费一些时间
    //+ 999999是为了多1毫秒,
    //当线程调用 Thread.sleep 方法的时候,JVM 会进行一个特殊的调用,将中断周期设置为 1ms
    //JVM每1ms检查一次,如果(deadline - currentTime)恰好是0.5ms,那么JVM可能检查的时候,这个任务时间过了,而不执行了,所以+ 999999
    long sleepTimeMs = (deadline - currentTime + 999999) / 1000000;

解释起来就是:比如说走1步需要10秒,那么就是休眠10秒,但是处理任务需要时间,那么这里就是减掉这个处理时间,一圈走完是多少秒就是多少秒,尽可能的准确,当然处理时间超过每步的时间,那就没办法了,有误差

  1. transferTimeoutsToBuckets:
    在这里插入图片描述这里就是取待分配队列的timeouts,然后计算需要多少圈+下标,再追加到那个下标bucket的next,addTimeout相当于链表的添加,博主也写过链表,不再多述。

  2. expireTimeouts:
    在这里插入图片描述判断bucket里面的任务:
    1.是否有需要执行的
    2.是否需要取消掉
    3.不执行,不取消,就把圈数-1

    到这里差不多就讲完了,整个时间轮,其实也很简单,看下面的图
    在这里插入图片描述
    这是Dubbo里面的时间轮,Kafka的层级时间轮还要更牛叉,下次在分析
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值