时间轮的golang实践浅析

引言

  • 下列代码模仿一段RPC请求的执行过程,执行后会有哪些问题:
    RPC代码示例
  • 答案:因为超时控制后未阻断后续请求,导致并发读写产生Panic
  • 思考:客户端发起 HTTP 请求后,如果在指定时间内没有收到服务器的响应,则自动断开连接,超时控制是如何工作的?

什么是时间轮

  • 思考:一定有一个类似于定时器的工具在执行,到时间后,中断任务。那么这个定时器是什么样的数据结构?又是如何实现这个定时功能的?
  • 理论上
    • 客户端发起请求后,立即创建(启动)一个 Timer:到期间隔为 d,到期后执行 “断开连接” 的操作。
    • 如果到期间隔 d 以内收到了服务器的响应,客户端就删除(停止)这个 Timer。
    • 如果一直没有收到响应,则 Timer 最终会到期,然后执行 “断开连接” 的操作。
  • 实际上
    • 现代的 Web 服务动辄管理 100w+ 的连接,每个连接都会有很多超时任务(比如发送超时、心跳检测等),如果每个超时任务都对应一个 Timer,性能会比较低下
  • 破解之法:采用时间轮实现的 Timer来管理连接任务,使得创建和删除连接任务的时间复杂度为 O(1)

时间轮种类和设计思路

  • 常见的时间轮实现有两种:
    • 简单时间轮(Simple Timing Wheel)—— 比如 Netty4 的 HashedWheelTimer
    • 层级时间轮(Hierarchical Timing Wheels)—— 比如 Kafka 的 Purgatory

简单时间轮

简单时间轮的设计思路
  • 一个 简单时间轮就是一个循环列表,列表中的每一格包含一个定时任务列表(双向链表)。一个时间单位为 u、大小为 n 的简单时间轮,可以包含的定时任务的最大到期间隔为 n*u。
  • 以 u 为 1ms、n 为 3 的简单时间轮为例,可以包含的定时任务的最大到期间隔为 3ms
简单时间轮示例

在这里插入图片描述

简单时间轮的实现
    index := 0
	timingWheels := make([]interface{
   }, 10)
	for {
    // 循环消费任务
		time.Sleep(1 * time.Second)
		index = index % 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值