NetCoreWeb集成Quart

251 阅读3分钟

这是我参与更文挑战的第13天,活动详情查看: 更文挑战

.NET Core可以创建“定时”后台服务在 ASP.NET Core 中使用托管服务实现后台任务(例如,每10分钟运行一次任务),但是自带的后台服务应用场景太局限。在实际场景中,我们通常需要指定更复杂的时间参数。例如 凌晨2点30,每天的上午10点,每两小时一次,当处理这些复杂的时间时,自带的解决方案就显得格格不入了。

为些Quartz.NET提供了强大的解决方案, 通过使用Cron表达式,您可以确保任务在特定时间运行,或仅在特定的几天运行,或这些时间的任意组合。

Quart.Net介绍

概述

Quartz主要有三部分组成任务(Job)、触发器(Trigger)和调度器(Schedule)。

任务

Job就是执行的作业,Job需要继承IJob接口,实现Execute方法。Job中执行的参数从Execute方法的参数中获取。

触发器

触发器常用的有两种:SimpleTrigger触发器和CronTrigger触发器。

调度器

调度器就是将任务和触发器绑定,让触发器触发的时候去执行任务。上一个简单的案例

案例

1、首先Nuget包引用

nuget install Quartz.AspNetCore

2、定义一个Job任务

/// <summary>
/// 创建IJob的实现类,并实现Excute方法
/// </summary>
public class TestJob : IJob
{
    public Task Execute(IJobExecutionContext context)
    {
        return Task.Run(() =>
        {
            Console.WriteLine("output testjob log");
        });
    }
}

3、Api控制器调用方法创建任务

[Route("quart")]
[ApiController]
public class QuartController : Controller
{
    private readonly ISchedulerFactory _schedulerFactory;

    public QuartController(ISchedulerFactory schedulerFactory)
    {
        _schedulerFactory = schedulerFactory;
    }

    [HttpGet("CreateTask")]
    public async Task<IActionResult> CreateTask()
    {
        //通过调度工厂获得调度器
        var _scheduler = await _schedulerFactory.GetScheduler();
        //开启调度器
        await _scheduler.Start();
        //创建一个触发器
        var trigger = TriggerBuilder.Create()
                        .WithSimpleSchedule(x => x.WithIntervalInSeconds(2).RepeatForever())//每两秒执行一次
                        .Build();
        //创建任务
        var jobDetail = JobBuilder.Create<TestJob>()
                        .WithIdentity("job", "group")
                        .Build();

        //将触发器和任务器绑定到调度器中
        await _scheduler.ScheduleJob(jobDetail, trigger);

        return new JsonResult(new { success = true });
    }

}

调用 localhost://quart/createtask 即可以看控制台看到每隔俩秒钟输出一段控制台信息。

实例使用场景

上述的案例是一种通过自己创建三元素的方式来创建任务,在一些通用场景下其实我们只关心定时任务的逻辑和执行的频率,其他我可以不考虑。

即领导给了我一个任务,任务的功能是:开发一个定时任务,每天02:30执行,清理数据库历史记录。那么开发者最方便的方式是什么?

伪代码

1、定义执行Job

class CleanJob{

	[cron表达式]
    public void cleanDatabase(){
		业务逻辑
    }
}

2、注入任务

services.Register(typeof(CleanJob))

如何能够通过这样的方式实现是最好的,但是现实是NetCore的quart.net现在还不支持这样的定义方式,java好像是可以的。

那有没有其他类似的方式可以实现上面的效果呢?

我给大家推荐一种方式

案例说明

1、定义一个初始化配置的服务注册

public static class QuartzIocExtend
{
    public static void AddJobAndTrigger<T>(this IServiceCollectionQuartzConfigurator quartz, IConfiguration config, string category = "Default") w
    {
        string quartKey = "Quartz";

        // 泛型Job的name
        string jobName = typeof(T).Name;

        // 从appsetting.json中获取任务job的corn执行表达式
        var configKey = $"{quartKey}:{category}:{jobName}";
        var cronSchedule = config[configKey];

        // 校验cron表达式存在
        if (string.IsNullOrEmpty(cronSchedule))
        {
            throw new Exception($"No Quartz.NET Cron schedule found for job in configuration at {configKey}");
        }

        // 注册job
        var jobKey = new JobKey(jobName);
        quartz.AddJob<T>(opts => opts.WithIdentity(jobKey));

		//为job添加调度器
        quartz.AddTrigger(opts => opts
            .ForJob(jobKey)
            .WithIdentity(jobName + "-cron-trigger")
            .WithCronSchedule(cronSchedule)); 
    }

2、ConfigureServices中注册

//quartz 定时服务
services.AddQuartz(q =>
{
    q.UseMicrosoftDependencyInjectionScopedJobFactory();

    q.AddJobAndTrigger<TestJob>(configuration);
});

3、配置文件定义cron表达式

"Quartz": {
  "Default": {
  	//5秒钟执行一次
  	"TestJob":"0/5 * * * * ? *"
  }
}

4、执行测试

测试结果正确,每五秒钟输出文本

参考

Quart.net官方文档

在.NET Core 中使用Quartz.NET

.Net Core中使用Quartz.NET

Quartz.Net使用教程

[在ASP.NET Core中创建基于Quartz.NET托管服务轻松实现作业调度](