cdn如何做网站备案,酒店网站建站,中文企业网站模板,东莞门户网站建设方案长话短说#xff0c;今天聊一聊分布式定时任务#xff0c;我的流水账笔记#xff1a;ASP.NET CoreQuartz.Net实现web定时任务AspNetCore结合Redis实践消息队列细心朋友稍一分析#xff0c;就知道还有问题#xff1a;水平扩展后的WebApp的Quartz.net定时任务会多次触发今天聊一聊分布式定时任务我的流水账笔记ASP.NET CoreQuartz.Net实现web定时任务AspNetCore结合Redis实践消息队列细心朋友稍一分析就知道还有问题水平扩展后的WebApp的Quartz.net定时任务会多次触发 因为webapp实例使用的是默认的RAMJobStore, 多实例在内存中都维护了Job和Trigger的副本.我的定时任务是同步任务多次执行倒是没有太大问题但对于特定业务的定时任务 多次执行可能是致命问题。基于此来看看Quartz.net 分布式定时任务的姿势AdoJobStore很明显水平扩展的多实例需要一个 独立于web实例的机制来存储Job和Trigger.Quartz.NET提供ADO.NET JobStore来存储任务数据。先使用SQL脚本在数据库中生成指定的表结构执行脚本之后会看到数据库中多出几个以 QRTZ_开头的表配置Quartz.net使用AdoJobStore可采用编码形式或者 quartz.config形式添加配置快速实践1. 预先生成Job、Trigger表从https://github.com/quartznet/quartznet/tree/master/database/tables 下载合适的数据库表脚本 生成指定的表结构2. 添加AdoJobStore本次使用编码方式添加AdoJobStore配置。首次启动会将代码中Job和Trigger持久化到sqlite后面就直接从sqlite中加载Job和Triggerusing System;
using System.Collections.Specialized;
using System.Data;
using System.Threading.Tasks;
using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Logging;
using Quartz;
using Quartz.Impl;
using Quartz.Impl.AdoJobStore.Common;
using Quartz.Spi;namespace EqidManager
{using IOCContainer IServiceProvider;public class QuartzStartup{public IScheduler Scheduler { get; set; }private readonly ILogger _logger;private readonly IJobFactory iocJobfactory;public QuartzStartup(IOCContainer IocContainer, ILoggerFactory loggerFactory){_logger loggerFactory.CreateLoggerQuartzStartup();iocJobfactory new IOCJobFactory(IocContainer);DbProvider.RegisterDbMetadata(sqlite-custom, new DbMetadata(){AssemblyName typeof(SqliteConnection).Assembly.GetName().Name,ConnectionType typeof(SqliteConnection),CommandType typeof(SqliteCommand),ParameterType typeof(SqliteParameter),ParameterDbType typeof(DbType),ParameterDbTypePropertyName DbType,ParameterNamePrefix ,ExceptionType typeof(SqliteException),BindByName true});var properties new NameValueCollection{[quartz.jobStore.type] Quartz.Impl.AdoJobStore.JobStoreTX, Quartz,[quartz.jobStore.useProperties] true,[quartz.jobStore.dataSource] default,[quartz.jobStore.tablePrefix] QRTZ_,[quartz.jobStore.driverDelegateType] Quartz.Impl.AdoJobStore.SQLiteDelegate, Quartz,[quartz.dataSource.default.provider] sqlite-custom,[quartz.dataSource.default.connectionString] Data SourceEqidManager.db,[quartz.jobStore.lockHandler.type] Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz,[quartz.serializer.type] binary};var schedulerFactory new StdSchedulerFactory(properties);Scheduler schedulerFactory.GetScheduler().Result;Scheduler.JobFactory iocJobfactory;}public async TaskIScheduler ScheduleJob(){var _eqidCounterResetJob JobBuilder.CreateEqidCounterResetJob().WithIdentity(EqidCounterResetJob).Build();var _eqidCounterResetJobTrigger TriggerBuilder.Create().WithIdentity(EqidCounterResetCron).StartNow()//每天凌晨0s.WithCronSchedule(0 0 0 * * ?) Seconds,Minutes,HoursDay-of-MonthMonthDay-of-WeekYearoptional field.Build();// 这里一定要先判断是否已经从SQlite中加载了Job和Triggerif (!await Scheduler.CheckExists(new JobKey(EqidCounterResetJob)) !await Scheduler.CheckExists(new TriggerKey(EqidCounterResetCron))){await Scheduler.ScheduleJob(_eqidCounterResetJob, _eqidCounterResetJobTrigger);}await Scheduler.Start();return Scheduler;}public void EndScheduler(){if (Scheduler null){return;}if (Scheduler.Shutdown(waitForJobsToComplete: true).Wait(30000))Scheduler null;else{}_logger.LogError(Schedule job upload as application stopped);}}
}
上面是Quartz.NET 从sqlite中加载Job和Trigger的核心代码这里要提示两点① IOCJobFactory 是自定义JobFactory目的是与ASP.NET Core原生依赖注入结合② 在调度任务的时候先判断是否已经从sqlite加载了Job和Trigger3.添加Quartz.Net UI轮子附赠Quartz.NET的调度UI: CrystalQuartz 方便在界面管理和调度任务① Install-Package CrystalQuartz.AspNetCore -IncludePrerelease② Startup启用CrystalQuartzusing CrystalQuartz.AspNetCore;
/** app is IAppBuilder* scheduler is your IScheduler (local or remote)*/
var quartz app.ApplicationServices.GetRequiredServiceQuartzStartup();
var _schedule await quartz.ScheduleJob();
app.UseCrystalQuartz(() scheduler);
③ 在localhost:YOUR_PORT/quartz地址查看调度总结输出Quartz.net以AdoJobStore支撑分布式定时任务解决多实例多次触发的问题快速抛出轮子Quartz.Net UI库https://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/job-stores.htmlhttps://github.com/guryanovev/CrystalQuartz