Quartz.net的最佳实践

打印 上一主题 下一主题

主题 777|帖子 777|积分 2331

Quartz.NET 官网
Quartz.net是什么

Quartz.NET 是一个功能齐全的开源作业调度系统,他的前身来源于java的Quartz.Quartz.net安装和使用

基于visual studio引用安装,其他IDE类似,或者下载DLL手动引用也是可以的;运行环境基于.net core,源.net程序类似 Quartz.net的架构和关键属性以及方法

三个主要的概念


  • scheduler 作业调度,作业计划在给定触发器发生时运行,实际就是领导
  • job 作业,实现简单 IJob 接口的任何 .NET 类,实际就是干活的员工
  • trigger 侦听器,负责捕获调度事件以监视或控制作业,实际就是监工
可以这样理解:

监工发现员工偷懒了,报告给领导,领导知道后,给员工派了很多活,导致了员工天天996. 大概是这么个关系;同时呢,一个员工可以被多个监工监理,同理一个监工也可以监理多个员工,他们是多对多的关系;多个员工也可以共属于一个领导,当然也可以一个领导只有一个员工,他们直接也是多对多的关系 Quartz.net的一些关键属性

类型 
ISchedulerFactorySchedulerBuilder的工厂类
IScheduler用于与调度程序交互的主要 API
SchedulerBuilder用于定义/构建调度程序实例,需要 Quartz 3.1 或更高版本
IJobFactoryJobBuilder的工厂类
IJob由您希望由调度程序执行的组件实现的接口
IJobDetail用于定义作业的实例
JobBuilder用于定义/构建 JobDetail 实例,这些实例定义作业的实例
TriggerBuilder用于定义/构建触发器实例
ITrigger定义执行给定作业的计划的一个组件,作业可以有多个关联的触发器
ListenerManager侦听器事件,例如:执行job工作之前,之后触发等等,同时也可用于触发器侦听
 IServiceCollectionQuartzConfigurator 参数

Scheduler Name调度作业的名称
Scheduler IdSchedulerId
Max Batch Size同时执行job的最大数量
InterruptJobsOnShutdown 
InterruptJobsOnShutdownWithWait 
BatchTriggerAcquisitionFireAheadTimeWindow 
 在通用host或者webhost中的最佳实践

通用host或者webhost代码是一样的
执行流程


  • 在通用主机服务中注入服务AddQuartz,AddQuartzHostedService
  • 在AddQuartz中配置调度作业的基本属性(SchedulerId等等)和调度器以及作业(ScheduleJob,AddJob,AddTrigger);可以在这个地方写入所有的调度作业,也可以写入一个initjob作业,在主机完全启动5秒后执行相应的业务(可规避掉某些依赖服务未启动的问题)
  • 在initjob中,初始化其他定时任务。官网介绍job只能有一个无参的构造函数,但我亲测可以注入(笑脸)
  • 关于job和reigger的具体参数,可查看官网
如下

以下代码和执行结果,其中执行顺序一目了然代码
  1.    static void Main(string[] args)
  2.         {
  3.             Console.WriteLine("Hello, World!");
  4.             LogProvider.SetCurrentLogProvider(new ConsoleLogProvider());
  5.             //通用主机配置
  6.             var build = Host.CreateDefaultBuilder(args)
  7.                 .ConfigureServices((host, services) =>
  8.                 {
  9.                     Console.WriteLine("--------1");
  10.                     
  11.                     //调度作业的唯一id的唯一标识,用于集群搭建cluster
  12.                     q.SchedulerId = "SchedulerId_01";
  13.                     //配置Quartz服务
  14.                     services.AddQuartz(q =>
  15.                     {
  16.                         Console.WriteLine("--------2");
  17.                         //依赖注入,ISchedulerFactory,Ijob等等
  18.                         q.UseMicrosoftDependencyInjectionJobFactory();
  19.                         //方法一和方法二使用不同方法的写法,本质基本是一样的
  20.                         //方法一
  21.                         q.ScheduleJob<InitJob>(
  22.                             trigger =>
  23.                             {
  24.                                 Console.WriteLine("--------33");
  25.                                 //WithIdentity 绑定触发器或者job的唯一属性和组
  26.                                 //TriggerKey,JobKey 都是代表唯一个属性和组
  27.                                 trigger.WithIdentity(new TriggerKey("trigger1", "triggergroup1"))
  28.                                        .WithSimpleSchedule(x => x.WithIntervalInSeconds(5))
  29.                                        // .StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(5)))
  30.                                        //  .WithDailyTimeIntervalSchedule(x => x.WithInterval(10, IntervalUnit.Second))
  31.                                        .WithDescription("init 描述");
  32.                             },
  33.                             jobConfigure =>
  34.                             {
  35.                                 Console.WriteLine("--------44");
  36.                                 jobConfigure.WithIdentity(new JobKey("Init1", "jobgroup1"));
  37.                             }
  38.                         );
  39.                         //方法二
  40.                         //q.AddJob<InitJob>(opts =>
  41.                         //{
  42.                         //    Console.WriteLine("--------3");
  43.                         //    opts.WithIdentity(new JobKey("Init1", "jobgroup1"));
  44.                         //});
  45.                         //q.AddTrigger(opts =>
  46.                         //{
  47.                         //    Console.WriteLine("--------4");
  48.                         //    //将job添加至触发器中
  49.                         //    opts.ForJob(new JobKey("Init1", "jobgroup1"))
  50.                         //    .WithIdentity("trigger1", "triggergroup1")
  51.                         //    .WithSimpleSchedule(x =>
  52.                         //    {
  53.                         //        Console.WriteLine("--------6");
  54.                         //        x.WithIntervalInSeconds(5);
  55.                         //        //.RepeatForever();
  56.                         //        //.WithRepeatCount(5);
  57.                         //    });
  58.                         //});
  59.                     });
  60.                     services.AddQuartzHostedService(options =>
  61.                     {   
  62.                         options.WaitForJobsToComplete = true;
  63.                     });
  64.                 }).Build();
  65.             //var schedulerFactory =  build.Services.GetService<ISchedulerFactory>();
  66.             //var scheduler = schedulerFactory.GetScheduler();
  67.             build.Run();
  68.             Console.WriteLine("--------7");
  69.         }
  70.     }
  71.     public class SampleJob : IJob
  72.     {
  73.         public SampleJob(ISchedulerFactory schedulerFactory, IJobFactory jobFactory)
  74.         {
  75.             Console.WriteLine("--------8");
  76.         }
  77.         public async Task Execute(IJobExecutionContext context)
  78.         {
  79.             Console.WriteLine("--------9");
  80.             context.JobDetail.JobDataMap.GetString("我是sample的job数据key");
  81.             Console.WriteLine($"我是sample的job数据key: {context.JobDetail.JobDataMap.GetString("我是sample的job数据key")}");
  82.             Console.WriteLine($"我是sample的Trigger数据key: {context.MergedJobDataMap.GetString("我是sample的Trigger数据key")}");
  83.         }
  84.     }
  85.     public class InitJob : IJob
  86.     {
  87.         public ISchedulerFactory _schedulerFactory;
  88.         public IJobFactory _jobFactory;
  89.         public InitJob(ISchedulerFactory schedulerFactory, IJobFactory jobFactory)
  90.         {
  91.             Console.WriteLine("--------12");
  92.             _schedulerFactory = schedulerFactory;
  93.             _jobFactory = jobFactory;
  94.         }
  95.         public async Task Execute(IJobExecutionContext context)
  96.         {
  97.             Console.WriteLine("--------13");
  98.             Console.WriteLine("InitJob Execute " + Random.Shared.Next(0, 100));
  99.             
  100.             //创建job
  101.             IJobDetail job = JobBuilder.Create<SampleJob>()
  102.                                 //写入参数
  103.                                 .UsingJobData("我是sample的job数据key", "我是sample的job数据value")
  104.                                 .WithIdentity("sample1", "jobgroup1").Build();
  105.             //创建触发器
  106.             ITrigger trigger = TriggerBuilder.Create()
  107.                                    .UsingJobData("我是sample的Trigger数据key", "我是sample的Trigger数据value")
  108.                                    .WithIdentity("trigger_sample1", "triggergroup1")
  109.                                    .WithDescription("我是描述")
  110.                                    //通过corn符号来创建触发器
  111.                                    //.WithCronSchedule(taskOptions.CronExpression)
  112.                                    .WithSimpleSchedule(x =>
  113.                                        x.WithIntervalInSeconds(5) //5秒后执行
  114.                                        .RepeatForever()  //重复
  115.                                     )
  116.                                    .Build();
  117.             //通过工厂获取一个作业调度
  118.             var scheduler = await _schedulerFactory.GetScheduler();
  119.             //绑定一个job的事件侦听器,从执行顺序上看 new JobListen是一个单例类
  120.             scheduler.ListenerManager.AddJobListener(new JobListen(), KeyMatcher<JobKey>.KeyEquals(new JobKey("sample1", "jobgroup1")));
  121.             //将作业和从触发器绑定至作业调度上
  122.             await scheduler.ScheduleJob(job, trigger);
  123.             //启动作业调度
  124.             await scheduler.Start();
  125.             Console.WriteLine("--------14");
  126.         }
  127.     }
  128.     //作业侦听器
  129.     public class JobListen : JobListenerSupport
  130.     {
  131.         public JobListen()
  132.         {
  133.             Console.WriteLine("--------20");
  134.         }
  135.         public override string Name { get { return "JobListen20"; } }
  136.         //调用job之前执行
  137.         public override Task JobToBeExecuted(IJobExecutionContext context, CancellationToken cancellationToken)
  138.         {
  139.             Console.WriteLine("--------21");
  140.             return base.JobToBeExecuted(context, cancellationToken);
  141.         }
  142.     }
  143.     //日志组件
  144.     public class ConsoleLogProvider : ILogProvider
  145.     {
  146.         public Logger GetLogger(string name)
  147.         {
  148.             return (level, func, exception, parameters) =>
  149.             {
  150.                 if (level >= LogLevel.Info && func != null)
  151.                 {
  152.                     Console.WriteLine("[" + DateTime.Now.ToLongTimeString() + "] [" + level + "] " + func(), parameters);
  153.                 }
  154.                 return true;
  155.             };
  156.         }
  157.         public IDisposable OpenNestedContext(string message)
  158.         {
  159.             throw new NotImplementedException();
  160.         }
  161.         public IDisposable OpenMappedContext(string key, object value, bool destructure = false)
  162.         {
  163.             throw new NotImplementedException();
  164.         }
  165.     }
复制代码
执行结果

  
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

知者何南

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表