关于定时器的设计学习记录(学习他人资料)和思考---定时任务 超时控制 频率限制
Posted it_worker365
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于定时器的设计学习记录(学习他人资料)和思考---定时任务 超时控制 频率限制相关的知识,希望对你有一定的参考价值。
JDK DelayQueue 内部一个PriorityQueue保存所有的delay对象,堆顶保存了快到期的任务
消息相关网站:
1. 客户端轮询服务器获取消息
2. comet长连接推送消息,实时性,客户端服务器端压力小(如果管理长连接)
JS带着用户信息请求长连接,服务器用list/queue保存连接,另起一个线程判断过期,遍历性能太差,只能用有序的queue,但重连复用之后就没序了,所以单一数据结构无法解决
以网文为例,检查用户(单机TCP十万级别)是否离线(30S内没消息)。
通用原则: 建立一个map(ID,最后一次消息时间),新来的请求不断更新该map
思路1:
启动一个timer来轮询这个map。-----只启动一个timer,但轮询效率低
思路2:
更新并对该ID请求包启动一个timer,30S之后触发。-----启动太多timer耗资源
思路3:
建立0-30的环形队列,每个slot为一个set<ids>任务集合,还有一个map<id,index>记录每个id投射到哪个slot,启动一个timer让队列每秒移动一格,设置currentIndex指针标志当前位置,当有请求来到,查找map到slot,删除slot对应的id,新增id到currentIndex的上一个位置,更新map。currentIndex每秒清理一个slot。
优点在于只要一个timer,且每秒只运行一次,批量才做超时
netty中类似设计:
HashedWheelTimer(高效处理大量定时任务, 且任务对时间精度要求相对不高, 比如链接超时管理等场景, 缺点是, 内存占用相对较高.):
Set<Task>[] 数组, 每个槽位(slot)表示一个 Set<Task>
tickDuration: 每 tick 一次的时间间隔, 每 tick 一次就会到达下一个槽位(上例为1S)
ticksPerWheel: 轮中的 slot 数(上例为30)
如果任务太慢,线程队列单独处理
如果任务时间跨度很大,数量多,单个HashedWheelTimer round很大,单个slot中任务列表很长,可以考虑分级HashedWheelTimer
以上是关于关于定时器的设计学习记录(学习他人资料)和思考---定时任务 超时控制 频率限制的主要内容,如果未能解决你的问题,请参考以下文章