net 控制台 定时_.NET Core实现基于Quart.Net的任务管理
(給DotNet加星標(biāo),提升.Net技能)
轉(zhuǎn)自:最美的不是下雨天cnblogs.com/zhaorong0912/p/13853061.html前段時(shí)間給公司項(xiàng)目升級.NET框架,把原先的任務(wù)管理平臺用.NET Core實(shí)現(xiàn),現(xiàn)做如下整理:
一、實(shí)現(xiàn)思路
之前的實(shí)現(xiàn)也是參考了博客園中其他文章實(shí)現(xiàn)的思路:
一個(gè)任務(wù)定義一個(gè)實(shí)現(xiàn)IJob接口的類,通過單獨(dú)的dll管理;
通過數(shù)據(jù)庫持久化、維護(hù)任務(wù),便于服務(wù)重啟時(shí)任務(wù)的恢復(fù);
定義一個(gè)管理任務(wù)的基礎(chǔ)服務(wù),輪詢數(shù)據(jù)庫中的任務(wù),根據(jù)任務(wù)的狀態(tài)維護(hù)任務(wù)的執(zhí)行;
新增任務(wù)時(shí),需要在數(shù)據(jù)庫中添加一條記錄,并且在任務(wù)管理的dll中添加一個(gè)實(shí)現(xiàn)IJob的類,基礎(chǔ)服務(wù)通過反射dll來構(gòu)建任務(wù)的實(shí)例添加到調(diào)度器中
由于業(yè)務(wù)代碼會(huì)頻繁調(diào)整,我們業(yè)務(wù)代碼從任務(wù)執(zhí)行中拆分出來,獨(dú)立部署成http服務(wù),任務(wù)的執(zhí)行就是調(diào)用一個(gè)http請求,這樣不同的任務(wù)就是請求的url不一樣,查看官方文檔( https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/more-about-jobs.html#job-instances )發(fā)現(xiàn),我們可以通過只創(chuàng)建一個(gè)基礎(chǔ)任務(wù)類,創(chuàng)建多個(gè)該任務(wù)類的實(shí)例來實(shí)現(xiàn)構(gòu)建多個(gè)任務(wù),IJobDetail中可以用JobDataMap對象來存儲Job實(shí)例的參數(shù),所以我們通過JobDataMap將請求url傳遞到任務(wù)的Execute()方法中,我們只需要在數(shù)據(jù)庫中補(bǔ)充任務(wù)請求的url信息就可以了,不需要單獨(dú)的dll去定義任務(wù)。
二、項(xiàng)目結(jié)構(gòu)
根據(jù)上面思路,我們只需要一個(gè)管理任務(wù)的基礎(chǔ)服務(wù)、一個(gè)Web管理平臺就可以實(shí)現(xiàn),為了保持項(xiàng)目簡單,把任務(wù)管理無關(guān)的功能合并在一個(gè)項(xiàng)目里,并且盡量排除無關(guān)的框架和功能點(diǎn),最終程序包含3個(gè)項(xiàng)目:
1、JobManage.Service:控制臺程序,管理任務(wù)的基礎(chǔ)服務(wù),通過Topshelf部署成windows服務(wù),如何部署參考:https://www.cnblogs.com/podolski/p/10054286.html
2、JobManage.Web:Web應(yīng)用程序,管理平臺,新增、暫停、恢復(fù)、刪除任務(wù),查看任務(wù)運(yùn)行日志;
3、JobManage.Core:類庫,提供業(yè)務(wù)基礎(chǔ)服務(wù),如數(shù)據(jù)庫操作等
動(dòng)態(tài)添加任務(wù):
IJobDetail jobDetail = JobBuilder.Create().WithIdentity(jobKey)
.UsingJobData("RequestUrl", job.RequestUrl)
.Build();ITrigger trigger = TriggerBuilder.Create()
.WithIdentity(group, name)
.StartNow()
.WithCronSchedule(job.CronExpression)
.Build();await context.Scheduler.ScheduleJob(jobDetail, trigger);
基礎(chǔ)任務(wù)類BaseJob.cs的Execute()方法:
public async Task Execute(IJobExecutionContext context){var url = context.JobDetail.JobDataMap.GetString("RequestUrl");var client = _clientFactory.CreateClient();var request = new HttpRequestMessage(HttpMethod.Post, url);var response = await client.SendAsync(request);if (response.IsSuccessStatusCode){await response.Content.ReadAsStringAsync();
}
}
三、任務(wù)狀態(tài)管理
這里定義7個(gè)任務(wù)狀態(tài):待執(zhí)行、執(zhí)行中、待暫停、已暫停、待恢復(fù)、待刪除、已刪除
web管理平臺維護(hù)任務(wù)(新增、暫停、恢復(fù)、刪除)時(shí)將任務(wù)狀態(tài)更新為待處理狀態(tài)(待執(zhí)行、待暫停、待恢復(fù)、待刪除),任務(wù)管理基礎(chǔ)服務(wù)定時(shí)遍歷業(yè)務(wù)任務(wù),根據(jù)數(shù)據(jù)庫中任務(wù)當(dāng)前的狀態(tài)修改任務(wù)的執(zhí)行,并且將數(shù)據(jù)庫中待處理任務(wù)狀態(tài)更新為已處理狀態(tài)(執(zhí)行中、已暫停、已刪除)
四、任務(wù)依賴注入服務(wù)
在任務(wù)類中我們用到了http服務(wù),我們需要在任務(wù)類中獲取http服務(wù),我們通過.Net Core注入和獲取服務(wù)的方式來實(shí)現(xiàn),這里主要是要自定義任務(wù)類實(shí)例的創(chuàng)建和獲取,官方文檔( https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/miscellaneous-features.html#jobfactory )中說明可以通過實(shí)現(xiàn) IJobFactory 接口,并且修改 IScheduler.JobFactory的屬性來實(shí)現(xiàn):
//自定義任務(wù)實(shí)例獲取public class JobFactory : IJobFactory{private readonly IServiceProvider _serviceProvider;public JobFactory(IServiceProvider serviceProvider){
_serviceProvider = serviceProvider;
}public virtual IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler){
IJobDetail jobDetail = bundle.JobDetail;
Type jobType = jobDetail.JobType;return _serviceProvider.GetService(jobType) as IJob;
}public virtual void ReturnJob(IJob job){var disposable = job as IDisposable;
disposable?.Dispose();
}}//修改IScheduler.JobFactory屬性_scheduler.JobFactory = serviceProvider.GetService();
官方文檔中也提供了依賴注入的示例:https://www.quartz-scheduler.net/documentation/quartz-3.x/packages/microsoft-di-integration.html#di-aware-job-factories
五、任務(wù)監(jiān)聽
我們需要記錄任務(wù)執(zhí)行的情況,Quartz.Net提供了任務(wù)監(jiān)聽功能,我們可以自己實(shí)現(xiàn)IJobListener接口,也可以繼承Quartz.Net框架中IJobListener的實(shí)現(xiàn)類JobListenerSupport來完成任務(wù)的監(jiān)聽,繼承JobListenerSupport 類時(shí)重寫對應(yīng)的方法來實(shí)現(xiàn)我們需要的操作,如下實(shí)現(xiàn)記錄任務(wù)上次執(zhí)行時(shí)間、下次執(zhí)行時(shí)間、執(zhí)行時(shí)長、執(zhí)行異常錯(cuò)誤信息
//監(jiān)聽實(shí)現(xiàn)public class JobListener : JobListenerSupport{private readonly JobRepository _jobRepository;private readonly JobRunLogRepository _jobRunLogRepository;public JobListener(JobRepository jobRepository, JobRunLogRepository jobRunLogRepository){
_jobRepository = jobRepository;
_jobRunLogRepository = jobRunLogRepository;
}public override string Name
{get { return "jobListener"; }
}public override async Task JobWasExecuted(IJobExecutionContext context, JobExecutionException jobException, CancellationToken cancellationToken = default){string group = context.JobDetail.Key.Group;string name = context.JobDetail.Key.Name;
DateTime fireTimeUtc = TimeZoneInfo.ConvertTimeFromUtc(context.FireTimeUtc.DateTime, TimeZoneInfo.Local);
DateTime? nextFireTimeUtc = null;if (context.NextFireTimeUtc != null)
{
nextFireTimeUtc = TimeZoneInfo.ConvertTimeFromUtc(context.NextFireTimeUtc.Value.DateTime, TimeZoneInfo.Local);
}if (!JobHelper.IsBaseJob(group, name))
{//更新任務(wù)執(zhí)行情況await _jobRepository.UpdateExecuteAsync(group, name, fireTimeUtc, nextFireTimeUtc);//記錄運(yùn)行日志double totalSeconds = context.JobRunTime.TotalSeconds;bool succ = true;string exception = string.Empty;if (jobException != null)
{
succ = false;
exception = jobException.ToString();
}
JobRunLog log = new JobRunLog(group, name, totalSeconds, fireTimeUtc, succ, exception);await _jobRunLogRepository.InsertAsync(log);
}
}
}//注冊監(jiān)聽器
JobListener listener = serviceProvider.GetService();
_scheduler.ListenerManager.AddJobListener(listener, GroupMatcher.AnyGroup());
六、總結(jié)
上述內(nèi)容只是記錄了搭建任務(wù)管理平臺時(shí)的思路和幾個(gè)關(guān)鍵的點(diǎn),沒有對Quartz.Net基礎(chǔ)功能、MongoDB操作做說明,官方文檔中包含了完整的說明,官方提供的源碼中也有完整的示例,建議閱讀官方文檔源碼來實(shí)現(xiàn)更高級的功能。
項(xiàng)目完整代碼地址:https://github.com/zhrong92/JobManage
項(xiàng)目截圖:
- EOF -
推薦閱讀??點(diǎn)擊標(biāo)題可跳轉(zhuǎn).NET 拾遺補(bǔ)漏:動(dòng)態(tài)構(gòu)建LINQ查詢表達(dá)式C# 9 record 并非簡單屬性 POCO 的語法糖.NET Core消息流處理流程看完本文有收獲?請轉(zhuǎn)發(fā)分享給更多人
關(guān)注「DotNet」加星標(biāo),提升.Net技能?
點(diǎn)贊和在看就是最大的支持??
總結(jié)
以上是生活随笔為你收集整理的net 控制台 定时_.NET Core实现基于Quart.Net的任务管理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: visio保存后公式变形_涨姿势了!仿真
- 下一篇: php跨域请求解决方案_swoft2 -