中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何掌握Quartz.net分布式定時任務的姿勢

發布時間:2021-11-18 16:01:47 來源:億速云 閱讀:220 作者:柒染 欄目:大數據

這篇文章給大家介紹如何掌握Quartz.net分布式定時任務的姿勢,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

引言

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

  • ASP.NET Core+Quartz.Net實現web定時任務    
  • AspNetCore結合Redis實踐消息隊列    

細心朋友稍一分析,就知道還有問題:
水平擴展后的WebApp的Quartz.net定時任務會多次觸發, 因為webapp實例使用的是默認的RAMJobStore, 多實例在內存中都維護了Job和Trigger的副本.

我的定時任務是同步任務,多次執行倒是沒有太大問題,但對于特定業務的定時任務, 多次執行可能是致命問題。

基于此,來看看Quartz.net 分布式定時任務的姿勢

 

AdoJobStore

很明顯,水平擴展的多實例需要一個 獨立于web實例的機制來存儲Job和Trigger.

Quartz.NET提供ADO.NET JobStore來存儲任務數據。

  1. 先使用SQL腳本在數據庫中生成指定的表結構

執行腳本之后,會看到數據庫中多出幾個以 QRTZ_開頭的表

  1. 配置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和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();
       
          // 這里一定要先判斷是否已經從SQlite中加載了Job和Trigger
           if (!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和Trigger

 
3.添加Quartz.Net UI輪子

附贈Quartz.NET的調度UI: CrystalQuartz, 方便在界面管理和調度任務
① 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地址查看調度

如何掌握Quartz.net分布式定時任務的姿勢    

關于如何掌握Quartz.net分布式定時任務的姿勢就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

汉中市| 陈巴尔虎旗| 雅安市| 河池市| 宁陵县| 含山县| 崇左市| 应用必备| 五莲县| 吐鲁番市| 钟山县| 泊头市| 德保县| 和田县| 克山县| 武隆县| 常熟市| 平度市| 瑞丽市| 兴文县| 鞍山市| 布尔津县| 昌都县| 方正县| 湖州市| 庆城县| 元江| 石狮市| 通许县| 肥东县| 资源县| 弋阳县| 全南县| 诸暨市| 岱山县| 嘉黎县| 高碑店市| 辽阳市| 高安市| 理塘县| 丹阳市|