无需Get更多技能,快速打造一个可持久化的任务调度
項目總是很忙,忙里偷閑還是要總結(jié)一下,前一段時間,由于項目中需要,我們需要很多定時匯總數(shù)據(jù)的情況,項目初期主要使用sql server 計劃任務(wù)實現(xiàn)對數(shù)據(jù)的匯總與統(tǒng)計,但是開發(fā)到一定時間內(nèi),需求提出了很多自動任務(wù)的功能,很多不是能夠在SQL Server中進行解決的,例如訂單關(guān)閉前多少分鐘內(nèi)發(fā)短信與郵箱告訴用戶,程序?qū)用婷刻靺R總錯誤日志發(fā)送至運維郵箱等,針對目前情況,簡單上網(wǎng)查了一下,決定使用TopShelf + Quartz 進行自動服務(wù)與任務(wù)調(diào)度,關(guān)于這兩項的介紹也很多了,廢話不多說,直接上代碼:
-
項目結(jié)構(gòu)圖如下:
?
任務(wù)調(diào)度與任務(wù)實現(xiàn)實質(zhì)是兩個完全不同的東西,所以自動服務(wù)于Job執(zhí)行是應(yīng)該分開的,所以任務(wù)創(chuàng)建時應(yīng)該吧Job加載到任務(wù)調(diào)度工程,最后告訴調(diào)度工廠,可以開始執(zhí)行任務(wù)之后,調(diào)度工廠會進行掃描Job,加載到內(nèi)存中挨個執(zhí)行。
-
IAutoService:?主要是聲明自動服務(wù)的接口模式,標記了服務(wù)的名稱,啟動時的加載等,統(tǒng)一由抽象類AutoServcieBase實現(xiàn)。
-
AutoServiceBase: 抽象類實現(xiàn)接口原則,規(guī)范自動任務(wù)的可選參數(shù),統(tǒng)一封裝調(diào)用,定義抽象方法與屬性,子類重寫。
定義好基礎(chǔ)服務(wù)后,接下來我們就要使用TopShelf搭建一個屬于我們自己的windows service了,代碼如下:
class Program{static void Main(string[] args){HostFactory.Run(x =>{x.Service<Service>(s =>{s.ConstructUsing(name => new Service());s.WhenStarted(tc => tc.Start());s.WhenStopped(tc => tc.Stop());s.WhenShutdown(tc => tc.Shutdown());});x.RunAsLocalSystem();x.SetDescription("服務(wù)集合,包含自動化消息,響應(yīng)隊列的領(lǐng)域事件");x.SetDisplayName("Test.Services");x.SetServiceName("Test.Services");});}}??topshelf是一個很簡單就能創(chuàng)建service的工具,它開源在GitHub TopShelf上,是一款快速搭建mono與windows service ,在編寫好我們的服務(wù)代碼,只需簡單地啟動代碼,就能創(chuàng)建一個持久化的服務(wù),不過想要兼容在Mono上也是非常簡單,只需加入如下一句代碼即可。
x.UseLinuxIfAvailable();?在我們的項目中windows service不僅僅是任務(wù)調(diào)度的寄宿形式,同時也是我們Event Store,對DDD感興趣的同學(xué)可以了解CQRS中SAGA模式中事件消費的形式,這個不在本文討論。
創(chuàng)建好我們的基礎(chǔ)服務(wù)后,接下來就是對任務(wù)調(diào)度工廠的設(shè)置,任務(wù)調(diào)度簡單來看,我們往往要使用事件監(jiān)聽,任務(wù)總調(diào)度工廠等等,這里Quartz很好的集成了這些,我們只需進行簡單的改造就能夠?qū)崿F(xiàn)如上功能。
-
QuartzScheduleJobManager:實現(xiàn)任務(wù)調(diào)度管理,在這里可以對總?cè)蝿?wù)調(diào)度工廠進行啟動,停止,加載Job等
IQuartzConfiguration是對IScheduler的一個簡單封裝,創(chuàng)建默認的調(diào)度程序:
1 public class QuartzConfiguration : IQuartzConfiguration 2 { 3 public IScheduler Scheduler => StdSchedulerFactory.GetDefaultScheduler(); 4 }?接下來就是任務(wù)監(jiān)聽,Quartz提供了一個很好的擴展,我們只需實現(xiàn)IJobListener接口即可,包含如下多個方法體:
查看字面意思,我們就能很好理解就是對每一個job在執(zhí)行中的階段所對應(yīng)的事件,方法體內(nèi)給出IJobExecutionContext當(dāng)前執(zhí)行的上下文,通過上下文我們可以輸出許多我們想要的東西,例如當(dāng)前執(zhí)行Job的Name,執(zhí)行時間,等等,也提供了JobExecutionException等異常信息,可以監(jiān)控Job執(zhí)行過程中發(fā)生的錯誤,很方便。
好了在我們的寄宿服務(wù),與基礎(chǔ)服務(wù)搭建完畢后,接下來就是要實現(xiàn)在業(yè)務(wù)系統(tǒng)中我們自身的邏輯結(jié)構(gòu)了,核心程序類Servcie.cs,在service中我們需要將我們?nèi)缟系呐渲眠M行加載,并同時掃描我們業(yè)務(wù)系統(tǒng)中的定時服務(wù)類,挨個進行啟動,代碼如下:
?
public class Service{/// <summary>/// 任務(wù)調(diào)度框架/// </summary>private IQuartzScheduleJobManager QuartzScheduleJobManager{get{return IocManager.Instance.Resolve<IQuartzScheduleJobManager>();}}/// <summary>/// 任務(wù)調(diào)度配置/// </summary>public IQuartzConfiguration QuartzConfiguration{get{return IocManager.Instance.Resolve<IQuartzConfiguration>();}}public Service(){try{//注冊我們的任務(wù)調(diào)度程序配置
IocManager.Register<IQuartzConfiguration, QuartzConfiguration>();
//注冊任務(wù)監(jiān)聽程序到Ioc
?IocManager.Register<IJobListener, QuartzJobListener>();
//聲明一個接口可以被多個實例實現(xiàn)IocManager.IocContainer.Kernel.Resolver.AddSubResolver(new ArrayResolver(TongTongMallBootstrapper.IocManager.IocContainer.Kernel, true));}catch (Exception ex){LogHelper.LogException(ex);}}
//設(shè)置我們的配置項public void QuartzConfigurationInitialize(){//Job映射工廠QuartzConfiguration.Scheduler.JobFactory = new QuartzJobFactory(IocManager.Instance);//Job 監(jiān)聽配置QuartzConfiguration.Scheduler.ListenerManager.AddJobListener(IocManager.Instance.Resolve<IJobListener>());}/// <summary>/// 基礎(chǔ)類服務(wù)/// </summary>public void Start(){//訂閱各項自動服務(wù)IocManager.Instance.IocContainer.Register(Classes.FromThisAssembly().BasedOn<IAutoService>().WithService.Base()); QuartzConfigurationInitialize();RegisterService();}/// <summary>/// 停止自動服務(wù)/// </summary>public void Stop(){QuartzScheduleJobManager.ShutDown();}/// <summary>/// 結(jié)束自動服務(wù)/// </summary>public void Shutdown(){TongTongMallBootstrapper.Dispose();QuartzScheduleJobManager.ShutDown();}/// <summary>/// 注冊服務(wù)/// </summary>/// <param name="args"></param>public void RegisterService(){foreach (var service in IocManager.Instance.IocContainer.ResolveAll<IAutoService>()){if (service.IsEnable){LogHelper.Logger.Debug($"{service.ServiceName}服務(wù)正在啟動中...");service.Start();}}LogHelper.Logger.Debug($"任務(wù)總調(diào)度工廠啟動!");QuartzScheduleJobManager.Start();}}
?在系統(tǒng)中我們主要使用了IOC進行了一個服務(wù)的自動掃描與切入,在服務(wù)配置完畢后,接下來我們只需定義業(yè)務(wù)相關(guān)的自動服務(wù)即可,通過繼承我們的抽象類AutoServiceBase,接下來就很方便的打造每一個自動任務(wù)調(diào)度了,而關(guān)于Quartz的任務(wù)調(diào)度形式與時間配置,不是本文的重點介紹內(nèi)容,就不在詳說,不過在任務(wù)調(diào)度中我們也可以實現(xiàn)很多自定義的時間調(diào)度模式,例如自定義的節(jié)假日,或者每周一執(zhí)行任務(wù)調(diào)度都可以,這個需要進行進一步編碼實現(xiàn)。
由于公司方面,代碼就不在給連接資源下載了,代碼給出只是思路,當(dāng)然在這里面還可以有更多的擴展,而本文只是方便快速上手為第一原則,文章有寫的不當(dāng)?shù)牡胤?#xff0c;請及時指出,如本文對您有所幫助,也請點個推薦,您的肯定也是是我最大的動力。thanks
轉(zhuǎn)載于:https://www.cnblogs.com/doNetTom/p/6442201.html
總結(jié)
以上是生活随笔為你收集整理的无需Get更多技能,快速打造一个可持久化的任务调度的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hibernate查询-基本查询
- 下一篇: 让字体图标代替雪碧图,减少请求带宽