ScheduleMaster在上个月底更新到了2.0版本,在功能和代码以及文档上都往前跨了很大一步,详细信息能够参考这篇文章:http://www.javashuo.com/article/p-ocmxdrtm-ga.htmlhtml
对ScheduleMaster还不熟悉的朋友能够先移步做者的系列文章:https://www.cnblogs.com/hohoa/category/1628282.htmlgit
此次的更新点主要包含:github
开发了延时任务功能。算法
抽象出分布式锁服务并默认数据库实现。数据库
补充了单元测试。c#
补充了几篇文档。api
修复了已知的bug。dom
其中的重头戏天然是延时任务功能,所谓的延时任务就是在指定时刻执行指定逻辑,这在平时需求开发中是很是常见的,做为一款功能齐全的调度系统这固然也是必备的功能。分布式
关于延时任务的实现原理我早期写过一篇文章《采用简易的环形延时队列处理秒级定时任务的解决方案》来介绍,ScheduleMaster也是在这个基础上改进而来。post
固然了,其余的实现方式也还有不少,主流的实现方案能够参考下面这篇文章,整理的比较齐全:http://www.javashuo.com/article/p-gvpspray-bc.html
我采用的就是比较经典的时间轮算法,原理就再也不重复介绍了能够移步到我前面的文章,下面看看实现效果。
咱们先经过一段测试代码看看延时队列的运行状况:
[Fact] public void Run() { //初始化容器 DelayPlanManager.Init(); Debug.WriteLine($"延时队列初始化完成时间:{DateTime.Now}"); Func<DelayQueueSlot, Task> callback = (result) => { var np = result as NotifyPlan; //模拟业务 Debug.WriteLine($"[{DateTime.Now}]ID:{np.Key},地址:{np.NotifyUrl},延迟秒数:{np.TimeSpan}"); return Task.CompletedTask; }; //模拟生产端写入任务 Task[] tasks = new Task[10]; for (int i = 0; i < 10; i++) { tasks[i] = new Task(() => { for (int k = 0; k < 200; k++) { int rndNum = new Random().Next(20, 500); DelayPlanManager.Insert(new NotifyPlan { NotifyUrl = "http://localhost:56655/api/1.0/value/delaypost", Key = Guid.NewGuid().ToString(), Callback = callback }, DateTime.Now.AddSeconds(rndNum)); } }, TaskCreationOptions.LongRunning); tasks[i].Start(); } Task.WaitAll(tasks); //构造消费者 while (true) { DelayPlanManager.Read(); System.Threading.Thread.Sleep(1000); } }
代码中建立了2000个延时任务,延时范围在20秒至500秒,因此咱们预测在程序启动后最快20秒就开始有信息输出,程序调式结果为:
当一个周期执行完后恰好过了1分钟:
分秒不差。
再看看在项目中的实际应用。
控制台建立任务页面:
不过实际使用中经过API方式建立显然更符合需求,因此一如既往地提供了开放API供业务系统接入,详细使用方式参考官方文档【使用API接入任务】。
系统提供了2种延迟模式供选择,即相对时间或绝对时间,能够在系统参数中配置,默认是使用相对时间。但使用相对时间模式有一点要注意,各节点间可能存在系统时间差致使任务被屡次执行,因此业务作好幂等性控制相当重要。
延时任务管理页面:
这里解释下任务的各个状态
已做废,表示已经从执行计划移除
已建立,表示刚建立好尚未加入执行计划
已就绪,表示已加入到执行计划中等待执行
已完成,表示执行成功
异常,表示执行失败
继续看一下任务运行状况。
单节点执行成功:
异常重试效果:
可用的参数配置:
更多好玩的东西欢迎下载体验~
喜欢的朋友请来一波star支持,并持续关注~~
传送门: