日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

3分钟掌握Quartz.net分布式定时任务的姿势

發(fā)布時(shí)間:2023/12/4 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 3分钟掌握Quartz.net分布式定时任务的姿势 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

長話短說,今天聊一聊分布式定時(shí)任務(wù),我的流水賬筆記:

  • ASP.NET Core+Quartz.Net實(shí)現(xiàn)web定時(shí)任務(wù)

  • AspNetCore結(jié)合Redis實(shí)踐消息隊(duì)列

細(xì)心朋友稍一分析,就知道還有問題:
水平擴(kuò)展后的WebApp的Quartz.net定時(shí)任務(wù)會(huì)多次觸發(fā), 因?yàn)閣ebapp實(shí)例使用的是默認(rèn)的RAMJobStore, 多實(shí)例在內(nèi)存中都維護(hù)了Job和Trigger的副本.

我的定時(shí)任務(wù)是同步任務(wù),多次執(zhí)行倒是沒有太大問題,但對于特定業(yè)務(wù)的定時(shí)任務(wù), 多次執(zhí)行可能是致命問題。

基于此,來看看Quartz.net 分布式定時(shí)任務(wù)的姿勢

AdoJobStore

很明顯,水平擴(kuò)展的多實(shí)例需要一個(gè) 獨(dú)立于web實(shí)例的機(jī)制來存儲(chǔ)Job和Trigger.

Quartz.NET提供ADO.NET JobStore來存儲(chǔ)任務(wù)數(shù)據(jù)。

  • 先使用SQL腳本在數(shù)據(jù)庫中生成指定的表結(jié)構(gòu)

  • 執(zhí)行腳本之后,會(huì)看到數(shù)據(jù)庫中多出幾個(gè)以 QRTZ_開頭的表

  • 配置Quartz.net使用AdoJobStore

  • 可采用編碼形式或者 quartz.config形式添加配置

    快速實(shí)踐

    1. 預(yù)先生成Job、Trigger表

    從https://github.com/quartznet/quartznet/tree/master/database/tables 下載合適的數(shù)據(jù)庫表腳本, 生成指定的表結(jié)構(gòu)

    2. 添加AdoJobStore

    本次使用編碼方式添加AdoJobStore配置。
    首次啟動(dòng)會(huì)將代碼中Job和Trigger持久化到sqlite,后面就直接從sqlite中加載Job和Trigger

    using 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.CreateLogger<QuartzStartup>();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 Source=EqidManager.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 Task<IScheduler> ScheduleJob(){var _eqidCounterResetJob = JobBuilder.Create<EqidCounterResetJob>().WithIdentity("EqidCounterResetJob").Build();var _eqidCounterResetJobTrigger = TriggerBuilder.Create().WithIdentity("EqidCounterResetCron").StartNow()//每天凌晨0s.WithCronSchedule("0 0 0 * * ?") Seconds,Minutes,Hours,Day-of-Month,Month,Day-of-Week,Year(optional field).Build();// 這里一定要先判斷是否已經(jīng)從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的核心代碼

    這里要提示兩點(diǎn):

    ①??IOCJobFactory 是自定義JobFactory,目的是與ASP.NET Core原生依賴注入結(jié)合
    ② 在調(diào)度任務(wù)的時(shí)候,先判斷是否已經(jīng)從sqlite加載了Job和Trigger

    3.添加Quartz.Net UI輪子

    附贈(zèng)Quartz.NET的調(diào)度UI: CrystalQuartz, 方便在界面管理和調(diào)度任務(wù)
    ① Install-Package CrystalQuartz.AspNetCore -IncludePrerelease
    ② Startup啟用CrystalQuartz

    using CrystalQuartz.AspNetCore; /** app is IAppBuilder* scheduler is your IScheduler (local or remote)*/ var quartz = app.ApplicationServices.GetRequiredService<QuartzStartup>(); var _schedule = await quartz.ScheduleJob(); app.UseCrystalQuartz(() => scheduler);

    ③ 在localhost:YOUR_PORT/quartz地址查看調(diào)度

    總結(jié)輸出

  • Quartz.net以AdoJobStore支撐分布式定時(shí)任務(wù),解決多實(shí)例多次觸發(fā)的問題

  • 快速拋出輪子:Quartz.Net UI庫

    • https://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/job-stores.html

    • https://github.com/guryanovev/CrystalQuartz?

    總結(jié)

    以上是生活随笔為你收集整理的3分钟掌握Quartz.net分布式定时任务的姿势的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。