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

  • 相关阅读:
    Discuz X 2.5 点点(伪静态)
    jq 、xml 省市级联动
    php memcache 初级使用(2)
    关于windows虚拟内存管理的页目录自映射
    SharePoint 2010 网络上的开发经验和资源
    SharePoint 2010 Reporting Services 报表服务器正在内置 NT AUTHORITY\SYSTEM 账户下运行 解决方法
    SharePoint 2010 Reporting Services 报表服务器无法解密用于访问报表服务器数据库中的敏感数据或加密数据的对称密钥 解决方法
    Active Directory Rights Management Services (AD RMS)无法检索证书层次结构。 解决方法
    SharePoint 2010 Reporting Services 报表服务器实例没有正确配置 解决方法
    SharePoint 2010 页面引用 Reporting Services 展现 List 报表
  • 原文地址:https://www.cnblogs.com/shapman/p/14218440.html
Copyright © 2011-2022 走看看