当前位置: 首页 > news >正文

【016】Dubbo3从0到1系列之时间轮

文章目录

  • 时间轮
    • 7.2 ⏱️时间轮
      • 7.2.1 时间轮的原优势
      • 7.2.2 Dubbo3中的时间轮的核心实现
      • 7.2.3 时间轮原理简述(以 Dubbo/Netty 实现为例)
      • 7.2.4 任务调度
      • 7.2.5 多级时间轮
      • 7.2.6 时间轮的原理

时间轮

7.2 ⏱️时间轮

Dubbo 3 中,为了高效处理大量定时任务(如心跳检测、超时重试、连接管理等),引入了时间轮(Timing Wheel)机制作为其内部定时任务调度的核心实现。时间轮是一种高性能、低开销的定时任务调度算法,特别适合处理大量短周期、低延迟精度要求的定时任务。

7.2.1 时间轮的原优势

  • O(1) 时间复杂度 的任务调度(理想情况下);
  • 内存友好,适合高频、短周期任务;
  • 天然支持任务分组与批量处理
  • 与 Netty 的时间轮设计思想一致(Dubbo 底层依赖 Netty)

7.2.2 Dubbo3中的时间轮的核心实现

  • Dubbo 3 的时间轮实现在 dubbo-common 模块中,核心类为:

    • HashedWheelTimer:时间轮调度器(直接复用或借鉴了 Netty 的 HashedWheelTimer 实现);
    • Timeout/TimerTask:任务抽象;

    在这里插入图片描述

💡 实际上,Dubbo 并未完全重写时间轮,而是基于 Netty 的 HashedWheelTimer 进行封装和适配,以保持与网络层的一致性。

7.2.3 时间轮原理简述(以 Dubbo/Netty 实现为例)

在这里插入图片描述

✅ 1. 数据结构

  • 一个环形数组(bucket array),每个槽(slot)是一个任务链表;
  • 一个工作线程(worker thread) 不断转动“指针”(tick);
  • 一个精度单位(tickDuration),如 100ms;
  • 一个轮数(wheel size),如 512。

例如:

  • tickDuration = 100ms
  • wheelSize = 512
  • 则时间轮最大支持定时:100ms × 512 = 51.2秒

超过最大时间的任务会通过“多轮”机制处理(类似多级时间轮)。

7.2.4 任务调度

  1. 用户提交一个延迟任务(如 250ms 后执行);
  2. 计算目标槽位:slot = (currentTick + delay / tickDuration) % wheelSize;
  3. 将任务加入对应 slot 的链表;
  4. 工作线程每 tickDuration 转动一次,处理当前 slot 中所有到期任务;
  5. 若任务未到期(因延迟过长),则重新计算并放入下一轮。

7.2.5 多级时间轮

对于超长时间任务(如几分钟),Dubbo/Netty 的 HashedWheelTimer 采用“降级到普通延迟队列”或“任务重调度”策略,而非实现多级时间轮(如 Kafka 的 Hierarchical Timing Wheels)。

7.2.6 时间轮的原理

HashedWheelTimer 是 Timer 接口的实现,它通过时间轮算法实现了一个定时器。HashedWheelTimer 会根据当前时间轮指针选定对应的槽(HashedWheelBucket),从双向链表的头部开始迭代,对每个定时任务(HashedWheelTimeout)进行计算,属于当前时钟周期则取出运行,不属于则将其剩余的时钟周期数减一操作。

时间轮对外提供了一个 newTimeout() 接口用于提交定时任务,在定时任务进入到 timeouts 队列之前会先调用 start() 方法启动时间轮,其中会完成下面两个关键步骤:

  • 确定时间轮的 startTime 字段
  • 启动 workerThread 线程,开始执行 worker 任务。

之后根据 startTime 计算该定时任务的 deadline 字段,最后才能将定时任务封装成 HashedWheelTimeout 并添加到 timeouts 队列。

分析时间轮指针一次转动的全流程:

  1. 时间轮指针转动,时间轮周期开始
  2. 清理用户主动取消的定时任务,这些定时任务在用户取消时,会记录到 cancelledTimeouts 队列中。在每次指针转动的时候,时间轮都会清理该队列。
  3. 将缓存在 timeouts 队列中的定时任务转移到时间轮中对应的槽中
  4. 根据当前指针定位对应槽,处理该槽位的双向链表中的定时任务
  5. 检测时间轮的状态。
    • 如果时间轮处于运行状态,则循环执行上述步骤,不断执行定时任务。
    • 如果时间轮处于停止状态,则执行下面的步骤获取到未被执行的定时任务并加入 unprocessedTimeouts 队列:
      • 遍历时间轮中每个槽位,并调用 clearTimeouts() 方法;
      • 对 timeouts 队列中未被加入槽中循环调用 poll()。
  6. 最后再次清理 cancelledTimeouts 队列中用户主动取消的定时任务。

✅ 1. 基本配置和状态管理

INSTANCE_COUNTER:  // 用于统计HashedWheelTimer实例的数量,防止创建过多实例
WARNED_TOO_MANY_INSTANCES: // 标记是否已经警告过实例数量过多
INSTANCE_COUNT_LIMIT: // 实例数量限制,默认为64
WORKER_STATE_UPDATER: // 使用原子更新器管理workerState状态
workerState: // 工作线程状态(初始化、已启动、已关闭)

✅ 2. 时间轮核心数据结构

// 每个tick的持续时间(纳秒),决定了时间轮的精度
private final long tickDuration; // 时间轮的桶数组,存储HashedWheelBucket对象
private final HashedWheelBucket[] wheel;// 用于计算时间轮索引的掩码,值为wheel.length - 1
private final int mask;// 执行时间轮任务的工作线程
private final Worker worker = new Worker();// workerThread: 工作线程的实际线程对象
private final Thread workerThread;

✅ 3. 同步和队列管理

startTimeInitialized: // 倒计时锁存器,用于等待工作线程初始化开始时间
timeouts: // 存储待处理的超时任务队列
cancelledTimeouts: // 存储已取消的超时任务队列
pendingTimeouts: // 统计待处理的超时任务数量
maxPendingTimeouts: // 最大允许的待处理超时任务数量限制

✅ 4. 时间管理

startTime: // 时间轮开始时间(纳秒),用于计算相对时间
tick: // 当前的tick计数,表示已经经过的tick数量

✅ 5. 系统相关

IS_OS_WINDOWS: // 标识当前操作系统是否为Windows,用于调整睡眠时间精度
http://www.dtcms.com/a/533945.html

相关文章:

  • 通州区住房和城乡建设部网站一级a做爰片免费网站瑜伽
  • cglib动态代理实现
  • 1.4.4 大数据方法论与实践指南-成本治理(省钱)
  • 自己的公司怎么做网站wordpress注册插件中文版
  • 中华建设杂志网站记者绍兴网站建设报价
  • 做家装的网站有哪些如何做网络推广
  • mysql存储过程和函数
  • 青海省高等级公路建设管局网站免费windows10云主机下载
  • 西安市建网站给单位做网站需要多少钱
  • 网站建设实践鉴定铜川泰士公馆建设网站
  • 电子商务网站有哪些内容上海网站开发团队
  • 长春电商网站建设wordpress js上传图片
  • 中国工商注册网官网淄博网站建设优化珍云
  • 营销型网站建设怎么做营销网站建设温州哪里有网站优化
  • 构建稳定数据管道:淘宝商品详情 API 的接入、监控与错误处理
  • Redis下载安装教程与使用,以及基础知识的应用
  • 哪个网站可以做视频外链企业网站建设的一般原则
  • 网站 盈利自己做个网站要多少钱
  • Gorm(十)计数 / 存在性
  • SAP 维护视图变式(Maintenance View Variants)
  • 苏州建设公司网站上海的公司地址
  • 景安网站备案要多久免费网址导航网站建设
  • 杨浦区建设小学网站首页WordPress有意思的代码特效
  • STM32F103C8T6_SPI完整教程
  • 使用蓝图组件
  • 哈尔滨网站建设培训班技术网站模版
  • 网站服务器和直播服务器一样吗深圳网站设计官网
  • 大型网站如何做别名夏津建设局网站
  • 20-Java-面向对象-static
  • 株洲网站建设优化网站建设方案书含合同