前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【项目升级】集成Quartz.Net Job实现(一)

【项目升级】集成Quartz.Net Job实现(一)

作者头像
老张的哲学
发布2022-04-11 14:11:49
6130
发布2022-04-11 14:11:49
举报
文章被收录于专栏:NetCore 从壹开始

这两天的新闻也是越来越多了,不仅Github接手了NPM,还有.NET 5也要新鲜出炉了(11月正式发布),当然还有MVP峰会也正在如火如荼的展开,会有哪些好的东西被碰撞出来,也是很期待的。这些天我也简单的开始了学习之路,网路一直不好,直播也就不好展开,但是肯定会有的,应该过不了多久,所以暂时通过文字来讲解吧。

BCVP(也就是Blog.Core和Vue的全家桶)项目开源一年多,我也一直在开发和维护,目标呢,也一直致力于打造一个开箱即用的丰富小框架,目前的核心功能如下:

也算是完成了九层了吧,剩下的10%属于锦上添花的功能,一般小项目可能用不上,但是中型项目是必须要用的,今天的重点就是说说作业调度Quzrtz.net,目前已经集成到了项目里,为了不影响Master分支,目前代码在is4分支上,感兴趣的小伙伴可以自行PULL下来看看,目前的效果是这样的,下篇文章会集成到Blog.Admin项目中。

(任务调度展示,可持久化到数据库)

本文重点参考Kawhi代码,自己做了调整:

【壹起学】1:Uwl.Admin开源框架基于QuartzNet的实现

这个系列我打算写三篇文章和一篇视频的形式,文章分为后端、前端、原理三篇,视频就是总体串一下,今天就是第一篇,简单说说后端的配置和操作,不讲原理。

为什么要使用Quartz.Net

关于Quartz.Net的概念、内容和工作原理UML这都不说了,相信你如果看到了这个文章标题,并点进来了,应该知道这是干啥的,也应该知道他的应用场景——任务调度,白话就是通过一定的简单配置,定时去执行一些任务,多见于统计和同步操作。

这里简单的贴一下它Github的数据,就足可见受欢迎度:

(我一直认为,好的开源项目,要看Closed了多少Issue)

其实本来我的项目中已经有了一套任务执行程序,用的还是微软的自带的HostingService

用起来是特别简单,几乎不用配置,只需要创建一个Service,然后直接写逻辑就行了,它会随着我们的运行的项目一起执行,如果说你的任务调度很简单,就是定时跑一个小方法,我还是比较推荐这个的,当然,这个也是有很多问题,比如不能手动动态配置,不能手动控制任务的启动、暂停、重启等多个操作,所以,应群友的号召,我就把.net中用的较多的Quzrtz给集成到了项目里,当然还有一个Hangfire也很流行,我目前公司老的项目中是用的这个Hangfire,但是我感觉有些臃肿了,不太应景NetCore这么优雅的高效框架。

后端如何配置Quartz.Net

01

创建任务数据库表以及四层服务

既然我们要动态配置到数据库里,那肯定就需要一个数据库表结构了,这个过程就是很简单的了,得益于我们有强大的Seed功能,无论是是CodeFirst生成数据库表结构,还是根据表结构利用FrameSeed生成四层文件,都很简单。

首先是创建实体类,然后生成到数据库中,我已经配置好了:

代码语言:javascript
复制
   /// <summary>
   /// 任务计划表
   /// </summary>
   public class TasksQz : RootEntity
    {
        /// <summary>
        /// 任务名称
        /// </summary>
        [SugarColumn(ColumnDataType = "nvarchar", Length = 200, IsNullable = true)]
        public string Name { get; set; }
        /// <summary>
        /// 任务分组
        /// </summary>
        [SugarColumn(ColumnDataType = "nvarchar", Length = 200, IsNullable = true)]
        public string JobGroup { get; set; }
        /// <summary>
        /// 任务运行时间表达式
        /// </summary>
        [SugarColumn(ColumnDataType = "nvarchar", Length = 200, IsNullable = true)]
        public string Cron { get; set; }
        /// <summary>
        /// 任务所在DLL对应的程序集名称
        /// </summary>
        [SugarColumn(ColumnDataType = "nvarchar", Length = 200, IsNullable = true)]
        public string AssemblyName { get; set; }
        /// <summary>
        /// 任务所在类
        /// </summary>
        [SugarColumn(ColumnDataType = "nvarchar", Length = 200, IsNullable = true)]
        public string ClassName { get; set; }
        /// <summary>
        /// 任务描述
        /// </summary>
        public string Remark { get; set; }
        /// <summary>
        /// 执行次数
        /// </summary>
        public int RunTimes { get; set; }
        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime? BeginTime { get; set; }
        /// <summary>
        /// 结束时间
        /// </summary>
        public DateTime? EndTime { get; set; }
        /// <summary>
        /// 触发器类型(0、simple 1、cron)
        /// </summary>
        public int TriggerType { get; set; }
        /// <summary>
        /// 执行间隔时间, 秒为单位
        /// </summary>
        public int IntervalSecond { get; set; }
        /// <summary>
        /// 是否启动
        /// </summary>
        public bool IsStart { get; set; } = false;
        /// <summary>
        /// 执行传参
        /// </summary>
        public string JobParams { get; set; }
        
        [SugarColumn(IsNullable = true)]
        public bool? IsDeleted { get; set; }
        /// <summary>
        /// 创建时间
        /// </summary>
        [SugarColumn(IsNullable = true)]
        public DateTime CreateTime { get; set; } = DateTime.Now;
      }

然后SeedData到数据库:

然后配置种子数据:

代码语言:javascript
复制
[
  {
    "Name": "博客管理",
    "JobGroup": "博客测试组",
    "Cron": "",
    "AssemblyName": "Blog.Core.Tasks",
    "ClassName": "Job_Blogs_Quartz",
    "Remark": "",
    "RunTimes": 0,
    "BeginTime": "",
    "EndTime": "",
    "TriggerType": 0,//0是simple模式,1的cron模式
    "IntervalSecond": 120,//2分钟执行一次
    "IsStart": true,
    "JobParams": "1",
    "IsDeleted": false,
    "CreateTime": "\/Date(1546272000000+0800)\/",
    "Id": 1
  }
]

(启动项目,自动SeedData)

生成到数据库后,然后我们就需要生成四层服务文件,因为我们的Blog.Core项目已经封装了代码生成器,还是两个,你可以用T4,也可以用DbFirstController.cs这个控制器方法,只需要FrameSeed.cs文件中,配置上表名就行了:

最后可以创建一个控制器,对这个表进行CURD操作,不赘述。核心要说的,还是我们的任务调度中心。

02

创建任务调度服务中心

当然,首先我们需要引用Nuget包:

代码语言:javascript
复制
// 在Blog.Core.Tasks 层安装
<PackageReference Include="Quartz" Version="3.0.7" />

新建QuartzNet文件夹,创建调度服务接口和实现类,具体的原理我会在第三篇简单说下:

代码语言:javascript
复制
namespace Blog.Core.Tasks
{
    /// <summary>
    /// 服务调度接口
    /// </summary>
    public interface ISchedulerCenter
    {

        /// <summary>
        /// 开启任务调度
        /// </summary>
        /// <returns></returns>
        Task<MessageModel<string>> StartScheduleAsync();
        /// <summary>
        /// 停止任务调度
        /// </summary>
        /// <returns></returns>
        Task<MessageModel<string>> StopScheduleAsync();
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="sysSchedule"></param>
        /// <returns></returns>
        Task<MessageModel<string>> AddScheduleJobAsync(TasksQz sysSchedule);
        /// <summary>
        /// 停止一个任务
        /// </summary>
        /// <param name="sysSchedule"></param>
        /// <returns></returns>
        Task<MessageModel<string>> StopScheduleJobAsync(TasksQz sysSchedule);
        /// <summary>
        /// 恢复一个任务
        /// </summary>
        /// <param name="sysSchedule"></param>
        /// <returns></returns>
        Task<MessageModel<string>> ResumeJob(TasksQz sysSchedule);
    }
}

主要就是利用IScheduler对Job进行处理,核心的逻辑和代码都在实现类类,今天暂时先不进行讲解,具体的可以查看SchedulerCenterServer.cs

配置好了服务以及调度中心,接下来就是创建一个个Job类了。

03

创建Job工作

顾名思义,我们要想实现任务调度,就需要创建很多个Job工作类,让调度中心自己根据相应的逻辑机制来去调度,我这里创建了一个简单的Job作为示例:

代码语言:javascript
复制
namespace Blog.Core.Tasks
{
    public class Job_Blogs_Quartz : JobBase, IJob
    {
        private readonly IBlogArticleServices _blogArticleServices;
        private readonly ITasksQzServices _tasksQzServices;

        public Job_Blogs_Quartz(IBlogArticleServices blogArticleServices, ITasksQzServices tasksQzServices)
        {
            _blogArticleServices = blogArticleServices;
            _tasksQzServices = tasksQzServices;
        }
        public async Task Execute(IJobExecutionContext context)
        {
            var executeLog = await ExecuteJob(context, async () => await Run(context));

            //var param = context.MergedJobDataMap;
            // 可以直接获取 JobDetail 的值
            var jobKey = context.JobDetail.Key;
            var jobId = jobKey.Name;

            // 也可以通过数据库配置,获取传递过来的参数
            JobDataMap data = context.JobDetail.JobDataMap;
            //int jobId = data.GetInt("JobParam");

            var model = await _tasksQzServices.QueryById(jobId);
            if (model != null)
            {
                model.RunTimes += 1;
                model.Remark += $"{executeLog}<br />";
                await _tasksQzServices.Update(model);
            }
        }
        public async Task Run(IJobExecutionContext context)
        {
            var list = await _blogArticleServices.Query();
            await Console.Out.WriteLineAsync("博客总数量" + list.Count.ToString());
        }
    }
}

通过接口调用

这个就很简单了,毕竟我们前后端分离,要通过接口的形式来对我们的任务进行调度,这里简单的列举一个就行了:

代码语言:javascript
复制
 /// <summary>
 /// 启动计划任务
 /// </summary>
 /// <param name="jobId"></param>
 /// <returns></returns>
 [HttpGet]
 public async Task<MessageModel<string>> StartJob(int jobId)
 {
     var data = new MessageModel<string>();
     // 获取任务服务
     var model = await _tasksQzServices.QueryById(jobId);
     // 开启job
     var ResuleModel = await _schedulerCenter.AddScheduleJobAsync(model);
     if (ResuleModel.success)
     {
         model.IsStart = true;
         data.success = await _tasksQzServices.Update(model);
     }
     if (data.success)
     {
         data.msg = "启动成功";
         data.response = jobId.ObjToString();
     }
     return data;
 }

最后的最后,不要忘记把相应的服务和接口进行注册:

好啦,关于后端如何配置任务调度Quzrtz.Net,就暂时说到这里了,下篇简单说下如何在前端配置页面吧,这两天我先设计着。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 NetCore 从壹开始 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么要使用Quartz.Net
  • 后端如何配置Quartz.Net
  • 通过接口调用
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档