(给DotNet加星标,提升.Net技能)

转自:最美的不是下雨天cnblogs.com/zhaorong0912/p/13853061.html

前段时间给公司项目升级.NET框架,把原先的任务管理平台用.NET Core实现,现做如下整理:

一、实现思路

之前的实现也是参考了博客园中其他文章实现的思路:

  • 一个任务定义一个实现IJob接口的类,通过单独的dll管理;

  • 通过数据库持久化、维护任务,便于服务重启时任务的恢复;

  • 定义一个管理任务的基础服务,轮询数据库中的任务,根据任务的状态维护任务的执行;

  • 新增任务时,需要在数据库中添加一条记录,并且在任务管理的dll中添加一个实现IJob的类,基础服务通过反射dll来构建任务的实例添加到调度器中

由于业务代码会频繁调整,我们业务代码从任务执行中拆分出来,独立部署成http服务,任务的执行就是调用一个http请求,这样不同的任务就是请求的url不一样,查看官方文档( https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/more-about-jobs.html#job-instances )发现,我们可以通过只创建一个基础任务类,创建多个该任务类的实例来实现构建多个任务,IJobDetail中可以用JobDataMap对象来存储Job实例的参数,所以我们通过JobDataMap将请求url传递到任务的Execute()方法中,我们只需要在数据库中补充任务请求的url信息就可以了,不需要单独的dll去定义任务。

二、项目结构

根据上面思路,我们只需要一个管理任务的基础服务、一个Web管理平台就可以实现,为了保持项目简单,把任务管理无关的功能合并在一个项目里,并且尽量排除无关的框架和功能点,最终程序包含3个项目:

1、JobManage.Service:控制台程序,管理任务的基础服务,通过Topshelf部署成windows服务,如何部署参考:https://www.cnblogs.com/podolski/p/10054286.html

2、JobManage.Web:Web应用程序,管理平台,新增、暂停、恢复、删除任务,查看任务运行日志;

3、JobManage.Core:类库,提供业务基础服务,如数据库操作等

动态添加任务:

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);

基础任务类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();    }}

三、任务状态管理

这里定义7个任务状态:待执行、执行中、待暂停、已暂停、待恢复、待删除、已删除

web管理平台维护任务(新增、暂停、恢复、删除)时将任务状态更新为待处理状态(待执行、待暂停、待恢复、待删除),任务管理基础服务定时遍历业务任务,根据数据库中任务当前的状态修改任务的执行,并且将数据库中待处理任务状态更新为已处理状态(执行中、已暂停、已删除)

四、任务依赖注入服务

在任务类中我们用到了http服务,我们需要在任务类中获取http服务,我们通过.Net Core注入和获取服务的方式来实现,这里主要是要自定义任务类实例的创建和获取,官方文档( https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/miscellaneous-features.html#jobfactory )中说明可以通过实现 IJobFactory 接口,并且修改 IScheduler.JobFactory的属性来实现:

//自定义任务实例获取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

五、任务监听

我们需要记录任务执行的情况,Quartz.Net提供了任务监听功能,我们可以自己实现IJobListener接口,也可以继承Quartz.Net框架中IJobListener的实现类JobListenerSupport来完成任务的监听,继承JobListenerSupport 类时重写对应的方法来实现我们需要的操作,如下实现记录任务上次执行时间、下次执行时间、执行时长、执行异常错误信息

//监听实现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))        {//更新任务执行情况await _jobRepository.UpdateExecuteAsync(group, name, fireTimeUtc, nextFireTimeUtc);//记录运行日志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);        }    }}//注册监听器JobListener listener = serviceProvider.GetService();_scheduler.ListenerManager.AddJobListener(listener, GroupMatcher.AnyGroup());

六、总结

上述内容只是记录了搭建任务管理平台时的思路和几个关键的点,没有对Quartz.Net基础功能、MongoDB操作做说明,官方文档中包含了完整的说明,官方提供的源码中也有完整的示例,建议阅读官方文档源码来实现更高级的功能。

项目完整代码地址:https://github.com/zhrong92/JobManage

项目截图:

- EOF -

推荐阅读  点击标题可跳转.NET 拾遗补漏:动态构建LINQ查询表达式C# 9 record 并非简单属性 POCO 的语法糖.NET Core消息流处理流程

看完本文有收获?请转发分享给更多人

关注「DotNet」加星标,提升.Net技能

点赞和在看就是最大的支持❤️

net 控制台 定时_.NET Core实现基于Quart.Net的任务管理相关推荐

  1. websocket一直无法链接_.NET Core 实现基于Websocket的在线聊天室

    什么是Websocket 我们在传统的客户端程序要实现实时双工通讯第一想到的技术就是socket通讯,但是在web体系是用不了socket通讯技术的,因为http被设计成无状态,每次跟服务器通讯完成后 ...

  2. 控制台发送get命令_.NET Core使用命令行参数库构建控制台应用程序

    前言 在我们开发中可能需要设计一次性应用程序,这些实用程序可以利用接近原始源代码的优势,但可以在与主Web应用程序完全独立的安全性上下文中启动.具体在 [管理过程](https://12factor. ...

  3. .net core 实现基于 cron 表达式的任务调度

    .net core 实现基于 cron 表达式的任务调度 Intro 上次我们实现了一个简单的基于 Timer 的定时任务,详细信息可以看这篇文章 . 但是使用过程中慢慢发现这种方式可能并不太合适,有 ...

  4. ASP.NET Core 实现基于 ApiKey 的认证

    ASP.NET Core 实现基于 ApiKey 的认证 Intro 之前我们有介绍过实现基于请求头的认证,今天来实现一个基于 ApiKey 的认证方式,使用方式参见下面的示例 Sample 注册认证 ...

  5. K8S——关于K8S控制台的yaml文件编写(基于上一章多节点K8S部署)

    K8S--关于K8S控制台的yaml文件编写(基于上一章多节点K8S部署) 一.yaml文件编写流程 二.证书自签 一.yaml文件编写流程 rbac.yaml---->secret.yaml- ...

  6. .net core 实现基于 JSON 的多语言

    .net core 实现基于 JSON 的实现多语言 Intro 上次我们提到了,微软默认提供基于资源文件的多语言本地化,个人感觉使用起来不是太方便,没有 json 看起来直观,于是动手造了一个轮子, ...

  7. asp.net core 自定义基于 HttpContext 的 Serilog Enricher

    asp.net core 自定义基于 HttpContext 的 Serilog Enricher Intro 通过 HttpContext 我们可以拿到很多有用的信息,比如 Path/QuerySt ...

  8. Nagios Core/Icinga 基于栈的缓冲区溢出漏洞

    漏洞名称: Nagios Core/Icinga 基于栈的缓冲区溢出漏洞 CNNVD编号: CNNVD-201402-484 发布时间: 2014-03-03 更新时间: 2014-03-03 危害等 ...

  9. 基于redis的分布式任务管理

    业务背景 系统中有各种定时任务,需要满足以下要求: 定时任务需要能够动态增删改查 需要能够设置任务的有效时间范围(只在此范围内执行) 任务执行周期需要能够灵活配置 需要能够轻松接入各种任务实现 需要能 ...

最新文章

  1. 本人常用的基础 linux命令
  2. C#XmlDocument无法读取utf-16文件
  3. ReviewForJob——最小生成树(prim + kruskal)源码实现和分析
  4. 云计算技术的跃进睿云智合专业先进水平
  5. 外贸人不知道的Facebook广告营销技巧和营销工具
  6. 磁共振立体定向仪行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  7. Js与flash交互:在html页面中用js与MyReport插件交互
  8. Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK
  9. Java 产品与软件下载
  10. 中国大学生mooc大数据技术原理与应用(林子雨)答案
  11. win10通过VMware使用教程
  12. 计算机显示去掉拼音分类,win10系统取消电脑文件显示以字母数字拼音分组的解决方法...
  13. Qt[每日一言|每日诗词]API调用
  14. NBUT - 1077 骨牌铺方格 【递推】
  15. 我的世界服务器修改皮肤指令,我的世界怎么拿指令来改皮肤的 | 手游网游页游攻略大全...
  16. 性能服务器漫画免费下拉式,奇妙漫画免费漫画
  17. c语言数字1 9转换英文,C语言提问:将一个月份数字转换成月份的英文名称
  18. MQTT下载安装和简单使用
  19. python爬虫——爬取拉勾上的职位信息
  20. Android 仿Windows Metro 界面UI

热门文章

  1. php页面修改器,读取器/修改器
  2. Insyde uefi 隐藏设置_安卓福利,手机桌面图标隐藏,找应用按字母轻松搞定!
  3. PooledDirectByteBuf源码分析
  4. 【绝对有用】Syntax error on token “throws“, @ expected after this token
  5. 计算机网络实验(华为eNSP模拟器)——第十章 Eth-Trunk(链路聚合)
  6. java tostring方法_Java程序员小伙启动项目报错,原来是使用了lombok
  7. 无法查找网络工作组计算机,XP系统弹出“无法查看工作组计算机”提示怎么办?...
  8. html5 制作神器,HTML5/Canvas 简单的泡沫生成器
  9. 三维球体换算到二维_AutoCAD三维入门,这些硬核干货要知道,看不懂建议备份收藏...
  10. java读取C++结构体,类型转换