Quartz.NET 中提供了 RAMJobStore 和 AdoJobStore 两种数据存储方式, 默认是 RAMJobStore(内存存储), 不需要任何其他配置内存的方式一般可能测试环境用的比较多, 生产环境可能更倾向于持久化存储, 当然还是要根据实际需求来定
我们也可以自定义 JobStore 方式, 比如 MongoDBDynamoDBRavenDBRedis 等等, 只要实现 IJobStore 接口即可不过常用的网上基本都有人已经有现成的, 如果想自己实现, 可以参考 Quartz.NET 或者其他实现方式的源码
RAMJobStore
RAMJobStore 是 JobStore 最简单的使用方式, 所有 Job 和 Trigger 相关的数据都保存在内存中, 性能上肯定是很高的 内存方式的缺点也非常明显, 如果重启或者宕机所有数据就会消失所以在 JobStore 的选择上, 要根据实际项目对数据的依赖性来决定到底用什么方式
在 Quartz.NET 作业调度 (二):Job 中提到通过 PersistJobDataAfterExecution 可以实现有状态的 Job 但基于 RAMJobStore 也只能保证程序不重启的情况下能保存状态, 一旦重启, 一切回到解放前, 每次看到都是类似下面截图的效果
AdoJobStore
AdoJobStore 是通过 ADO.NET 将数据存储在数据库中, 使用数据库的方式必然没有内存方式性能高, 但通过创建合理的数据库索引, 也不会差官方为我们提供了对应的 SQL 语言 github.com/quartznet/q, 我们只需要在自己的数据库上执行, 表和索引就全部创建完成了
除此之外, 我们需要增加一个配置文件 quartz.config 调度器启动的时候会自动加载文件内的配置, 注意这个文件需要修改属性 复制输出到目录 => 如果较新则复制 或 始终复制以代码的方式设置这些配置属性也可以, 个人觉得通过配置文件显得比较干净一些优先级: 代码设置 > quartz.config
说明: 文件内的 #开头代表注释, 在行最后加上 !END 表示之后的全部忽略
- # 数据连接字符串
- quartz.dataSource.myDS.connectionString=Database=Quartz;Server=172.17.30.108;User ID=sa;Password=mingdao!@#123
- # 数据库类型
- quartz.dataSource.myDS.provider=SqlServer
- # 设置存储类型
- quartz.jobStore.type=Quartz.Impl.AdoJobStore.JobStoreTX, Quartz
- # 驱动类型
- quartz.jobStore.driverDelegateType=Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz
- # 数据源名称, 于 quartz.dataSource 的属性名一样
- quartz.jobStore.dataSource=myDS
- #JobDataMaps 中的值只能是字符串, 具体可以看官方推荐这样设置的原因
- quartz.jobStore.useProperties=true
- # 数据存储序列号方式
- quartz.serializer.type=json
- // 创建作业调度器
- ISchedulerFactory factory = new StdSchedulerFactory();
- IScheduler scheduler = await factory.GetScheduler();
- await scheduler.Start();
- var jobDataMap = new JobDataMap();
- jobDataMap.Add("times", "1");
- // 创建一个作业
- IJobDetail job = JobBuilder.Create<HelloJob>()
- .WithIdentity("job1", "jobGroup1")
- .UsingJobData(jobDataMap)
- .Build();
- // 创建一个触发器
- ITrigger trigger = TriggerBuilder.Create()
- .WithIdentity("trigger1", "triggerGroup1")
- .StartNow()
- .WithSimpleSchedule(x => x
- .WithIntervalInSeconds(1)
- .WithRepeatCount(10))
- .Build();
- var jobExist = await scheduler.CheckExists(job.Key);
- if (!jobExist)
- {
- await scheduler.ScheduleJob(job, trigger);
- }
如下图, 执行了一定次数后, 应用程序被停止:
通过数据库查看到 Job 和 Trigger 的基本信息 Job DataTrigger 触发次数等应用程序再次重启, Trigger 和 Job Data 的数据都是延续之前的作业全部执行完毕后, Job 和 Trigger 失效, 数据也会自动被删除
Cluster
Quartz.NET 中集群配置还是比较简单的, 只需要增加两个配置属性就可以实现, 但 Quartz.NET 中的集群可能和想象的不太一样, 集群中的多个节点是不会同时工作的, 只有一个节点是处于工作状态, 其他节点属于待命状态, 只有当工作节点挂了, 其他节点中的一个才会自动升级为工作节点
官方并不推荐将多个节点部署到不同的服务器上, 因为毕竟是作业调度程序, 对时间一致性要求比较高, 不同的服务器可能存在时间差异, 所以如果部署到多台服务器要特别注意
- # 是否是集群模式
- quartz.jobStore.clustered=true
- # 自动生成唯一的 instanceId
- quartz.scheduler.instanceId=AUTO
node1 和 node2 多次重启的效果:
参考链接:
Quartz.NET Documentation
案例 Demo-QuartzNetJobStore
来源: https://juejin.im/entry/5ab68b26f265da237f1e4172