日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

无需Get更多技能,快速打造一个可持久化的任务调度

發(fā)布時間:2025/4/14 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 无需Get更多技能,快速打造一个可持久化的任务调度 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

    項目總是很忙,忙里偷閑還是要總結(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)。

1 public interface IAutoService 2 { 3 /// <summary> 4 /// 服務(wù)名稱 5 /// </summary> 6 string ServiceName { get; } 7 8 /// <summary> 9 /// 啟動方法 10 /// </summary> 11 void Start(); 12 13 /// <summary> 14 /// 是否啟用 15 /// </summary> 16 bool IsEnable { get; } 17 }
  • AutoServiceBase: 抽象類實現(xiàn)接口原則,規(guī)范自動任務(wù)的可選參數(shù),統(tǒng)一封裝調(diào)用,定義抽象方法與屬性,子類重寫。

1 public abstract class AutoServiceBase : IAutoService 2 { 3 public IQuartzConfiguration QuartzConfiguration { get; set; } 4 5 public IQuartzScheduleJobManager QuartzScheduleJobManager { get; set; } 6 7 public const string ServiceGroupName = "AutoService.Groups"; 8 9 /// <summary> 10 /// 服務(wù)名稱 11 /// </summary> 12 public virtual string ServiceName { get { return "服務(wù)啟動..."; } } 13 14 /// <summary> 15 /// 任務(wù)調(diào)度 16 /// </summary> 17 public virtual Action<TriggerBuilder> ConfigureTrigger { get; } 18 19 public virtual bool IsEnable { get { return true; } } 20 21 /// <summary> 22 /// 獲取服務(wù)方法名稱 23 /// </summary> 24 /// <returns></returns> 25 public abstract string GetServiceIdentiy(); 26 27 /// <summary> 28 /// 啟動任務(wù) 29 /// </summary> 30 public abstract void Start(); 31 32 }

定義好基礎(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等

1 public interface IQuartzScheduleJobManager 2 { 3 /// <summary> 4 /// 增加任務(wù)與任務(wù)調(diào)度到任務(wù)工廠 5 /// </summary> 6 /// <typeparam name="TJob"></typeparam> 7 /// <param name="configureJob">任務(wù)</param> 8 /// <param name="configureTrigger">任務(wù)調(diào)度</param> 9 /// <returns></returns> 10 Task ScheduleAsync<TJob>(Action<JobBuilder> configureJob, Action<TriggerBuilder> configureTrigger) where TJob : IJob; 11 12 /// <summary> 13 /// 啟動任務(wù) 14 /// </summary> 15 void Start(); 16 17 /// <summary> 18 /// 等待任務(wù)完成并停止任務(wù) 19 /// </summary> 20 void ShutDown(); 21 } 22 23 public class QuartzScheduleJobManager : IQuartzScheduleJobManager 24 { 25 private readonly IQuartzConfiguration _quartzConfiguration; 26 27 public QuartzScheduleJobManager( 28 IQuartzConfiguration quartzConfiguration) 29 { 30 _quartzConfiguration = quartzConfiguration; 31 } 32 33 /// <summary> 34 /// 增加任務(wù)與任務(wù)調(diào)度到任務(wù)工廠 35 /// </summary> 36 /// <typeparam name="TJob"></typeparam> 37 /// <param name="configureJob">任務(wù)</param> 38 /// <param name="configureTrigger">任務(wù)調(diào)度</param> 39 /// <returns></returns> 40 public Task ScheduleAsync<TJob>(Action<JobBuilder> configureJob, Action<TriggerBuilder> configureTrigger) 41 where TJob : IJob 42 { 43 var jobToBuild = JobBuilder.Create<TJob>(); 44 configureJob(jobToBuild); 45 var job = jobToBuild.Build(); 46 47 var triggerToBuild = TriggerBuilder.Create(); 48 configureTrigger(triggerToBuild); 49 var trigger = triggerToBuild.Build(); 50 51 _quartzConfiguration.Scheduler.ScheduleJob(job, trigger); 52 53 return Task.FromResult(0); 54 } 55 56 /// <summary> 57 /// 啟動任務(wù) 58 /// </summary> 59 public void Start() 60 { 61 //啟動任務(wù)調(diào)度框架 62 if (!_quartzConfiguration.Scheduler.IsStarted) 63 { 64 _quartzConfiguration.Scheduler.Start(); 65 } 66 } 67 68 /// <summary> 69 /// 等待任務(wù)完成并停止任務(wù) 70 /// </summary> 71 public void ShutDown() 72 { 73 if (_quartzConfiguration.Scheduler.IsStarted && !_quartzConfiguration.Scheduler.IsShutdown) 74 { 75 _quartzConfiguration.Scheduler.Shutdown(); 76 } 77 } 78 }

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接口即可,包含如下多個方法體:

  • JobExecutionVetoed
  • JobToBeExecuted
  • JobWasExecuted
  • 查看字面意思,我們就能很好理解就是對每一個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)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。