zoukankan      html  css  js  c++  java
  • .net 5中使用Quartz构建单机版定时任务器

    1、nuget包

    2、项目中添加三个类

    2.1 JobFactory
        public class JobFactory : IJobFactory
        {
            /// <summary>
            /// dotnet core 的 ioc
            /// </summary>
            private readonly IServiceProvider _serviceProvider;
    
            /// <summary>
            /// 构造注入
            /// </summary>
            /// <param name="serviceProvider"></param>
            public JobFactory(IServiceProvider serviceProvider)
                => _serviceProvider = serviceProvider;
    
            /// <summary>
            /// 按照startup里批量注册的job,创建一个指定类型的job
            /// </summary>
            /// <param name="bundle"></param>
            /// <param name="scheduler"></param>
            /// <returns></returns>
            public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
            {
                var serviceScope = _serviceProvider.CreateScope(); // 获得一个ioc对象,指定创建scope级别的实例(例如在job里面如果需要依赖注入ef,但是startup里面配置的ef是scope级别的话,这里就必须指定为scope,不然会报错,因为默认是创建单例,单例和scope线程内唯一是冲突的)。
                return serviceScope.ServiceProvider.GetService(bundle.JobDetail.JobType) as IJob; // 手动注入一个 job 后返回
            }
    
            public void ReturnJob(IJob job) { }
        }
    
    2.2 JobSchedule
        /// <summary>
        /// 在定义一个定时作业计划时所需要的数据
        /// 可以看成一个dto,为job创建schedule时用的
        /// </summary>
        public class JobSchedule
        {
            public JobSchedule(Type jobType, string cronExpression)
            {
                JobType = jobType;
                CronExpression = cronExpression;
            }
    
            /// <summary>
            /// 作业类型
            /// </summary>
            public Type JobType { get; }
            /// <summary>
            /// cron 表达式
            /// </summary>
            public string CronExpression { get; }
        }
    
    2.3 QuartzHostedService
        /// <summary>
        /// quartz 主机服务
        /// </summary>
        [DisallowConcurrentExecution]
        public class QuartzHostedService : IHostedService
        {
            /// <summary>
            /// 定时作业计划生成工厂,这一项在startup有配置集群模式
            /// </summary>
            private readonly ISchedulerFactory _schedulerFactory;
            /// <summary>
            /// 定时作业工厂
            /// </summary>
            private readonly IJobFactory _jobFactory;
            /// <summary>
            /// 定时作业计划集合,配合dotnet core的ioc注入进来
            /// </summary>
            private readonly IEnumerable<JobSchedule> _jobSchedules;
            /// <summary>
            /// 日志
            /// </summary>
            private readonly ILogger _logger;
            /// <summary>
            /// quartz scheduler
            /// </summary>
            private IScheduler _scheduler;
    
            /// <summary>
            /// 构造注入
            /// </summary>
            /// <param name="schedulerFactory"></param>
            /// <param name="jobFactory"></param>
            /// <param name="jobSchedules"></param>
            /// <param name="logger"></param>
            public QuartzHostedService(
                ISchedulerFactory schedulerFactory,
                IJobFactory jobFactory,
                IEnumerable<JobSchedule> jobSchedules,
                ILogger<QuartzHostedService> logger
                )
            {
                _schedulerFactory = schedulerFactory;
                _jobSchedules = jobSchedules;
                _jobFactory = jobFactory;
                _logger = logger;
            }
    
            /// <summary>
            /// 批量启动定时任务
            /// </summary>
            /// <param name="cancellationToken"></param>
            /// <returns></returns>
            public async Task StartAsync(CancellationToken cancellationToken)
            {
                _scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
                _scheduler.JobFactory = _jobFactory;
    
                // 循环遍历startup里注册的作业
                foreach (var jobSchedule in _jobSchedules)
                {
                    var job = CreateJob(jobSchedule);
                    var trigger = CreateTrigger(jobSchedule);
    
                    await _scheduler.ScheduleJob(job, trigger, cancellationToken);
                }
    
                await _scheduler.Start();
            }
    
            /// <summary>
            /// 停止
            /// </summary>
            /// <param name="cancellationToken"></param>
            /// <returns></returns>
            public async Task StopAsync(CancellationToken cancellationToken)
                => await _scheduler?.Shutdown(cancellationToken);
    
            /// <summary>
            /// 创建定时作业
            /// </summary>
            /// <param name="schedule"></param>
            /// <returns></returns>
            private static IJobDetail CreateJob(JobSchedule schedule)
            {
                return JobBuilder
                    .Create(schedule.JobType)
                    .WithIdentity(GenerateIdentity(schedule, IdentityType.Job))
                    .WithDescription(schedule.CronExpression)
                    .Build();
            }
    
            /// <summary>
            /// 创建触发器
            /// </summary>
            /// <param name="schedule"></param>
            /// <returns></returns>
            private static ITrigger CreateTrigger(JobSchedule schedule)
            {
                return TriggerBuilder
                    .Create()
                    .WithIdentity(GenerateIdentity(schedule, IdentityType.Trigger))
                    .WithCronSchedule(schedule.CronExpression)
                    .WithDescription(schedule.JobType.FullName)
                    .Build();
            }
    
            /// <summary>
            /// 生成一个标识(类似主键的意思)
            /// </summary>
            /// <param name="schedule"></param>
            /// <param name="identityType">标识类型,一个job作业,或者是trigger触发器</param>
            /// <returns></returns>
            private static string GenerateIdentity(JobSchedule schedule, IdentityType identityType)
            {
                switch (identityType)
                {
                    case IdentityType.Job:
                        return $"NdcPayInternal_Job_{schedule.JobType.Name}";
                    case IdentityType.Trigger:
                        return $"NdcPayInternal_Trigger_{schedule.JobType.Name}";
                }
    
                return schedule.JobType.FullName;
            }
    
            /// <summary>
            /// 标识类型
            /// </summary>
            private enum IdentityType
            {
                Job,
                Trigger
            }
        }
    

    3、startup里面注册一下上面三个

         #region quartz
    
         services.AddHostedService<QuartzHostedService>();
         services.AddSingleton<IJobFactory, JobFactory>();
         services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
    
         #endregion
    

    4、上面三步就已经是配置好了 Quartz ,接下来创建两个 job

    4.1 创建 MyJob1 和 MyJob2
        public class MyJob1 : IJob
        {
            /// <summary>
            /// 日志
            /// </summary>
            private readonly ILogger _logger;
    
            public MyJob1(ILogger<MyJob1> logger)
                => _logger = logger;
    
            public Task Execute(IJobExecutionContext context)
            {
                _logger.LogInformation("执行了我,我是 【job1】");
    
                return Task.CompletedTask;
            }
        }
    
        public class MyJob2 : IJob
        {
            /// <summary>
            /// 日志
            /// </summary>
            private readonly ILogger _logger;
    
            public MyJob2(ILogger<MyJob2> logger)
                => _logger = logger;
    
            public Task Execute(IJobExecutionContext context)
            {
                _logger.LogInformation("执行了我,我是 【job2】");
    
                return Task.CompletedTask;
            }
        }
    

    4.2 在startup中注册这两个 job

         services.AddTransient<MyJob1>();
         services.AddTransient(u => new JobSchedule(
             jobType: typeof(MyJob1),
             cronExpression: "0/10 * * * * ?")); // 10s执行一次
    
         services.AddTransient<MyJob2>();
         services.AddTransient(u => new JobSchedule(
             jobType: typeof(MyJob2),
             cronExpression: "0/15 * * * * ?")); // 15s执行一次
    

    运行之后:

    以上就是单机版的定时任务构建,下一篇文章会基于此,升级为高可用的Quzrtz集群。

    上述内容代码:https://github.com/book12138/QuartzSample

  • 相关阅读:
    careercup-C和C++ 13.6
    C++中名字隐藏,名字查找优先于类型检查
    careercup-C和C++ 13.5
    careercup-C和C++ 13.4
    careercup-C和C++ 13.3
    careercup-C和C++ 13.2
    careercup-C和C++
    careercup-排序和查找 11.7
    RMAN Catalog创建、配置和管理
    Linux一块网卡添加多个IP地址
  • 原文地址:https://www.cnblogs.com/shapman/p/14218440.html
Copyright © 2011-2022 走看看